This is an R Notebook which reproduces the analysis, tables and figures of the working paper "MetaMetaZipf. What do analyses of city size distributions have in common?". The data is stored on the MetaZipf GitHub repository.

Importing Data from the metaZipf project:

refs <- read.csv2("data/zipf_refs.csv", sep=';')
cites <- read.csv2("data/zipf_cites.csv", sep=',')
data <- read.csv2("data/zipf_meta.csv", sep=",", dec=".")
cname <- "data/FullText/"
docs <- Corpus(DirSource(cname))   
J2D <- read.csv2('journals2Disciplines.csv', sep=';')

Cleaning citation data

cites_out <- cites[67:1221,]
cites_out$YEAR <- as.numeric(gsub("\\D+", "", cites_out$REFID))
cites_out$JOURNAL <- gsub(".*\\d.", "", cites_out$REFID)
cites_out$AUTHOR <- gsub("\\d.*", "", cites_out$REFID)
cites_out$JOURNAL <- gsub("[[:punct:]]", " ", cites_out$JOURNAL)
cites_out$AUTHOR <- gsub("[[:punct:]]", " ", cites_out$AUTHOR)
cites_out <- data.frame(cites_out,J2D[match(cites_out$JOURNAL, J2D$JOURNAL),])
cites_out$DISCIPLINE <- cites_out$DISCPLINE
cites_out$DISCPLINE <- NULL
cites_out$JOURNAL.1 <- NULL
cites <- rbind(cites[1:66,],cites_out)
cites[is.na(cites)] <- 0
cites_within <- cites[1:66,c(1,6:71)]
head(cites)

Corpus analysis

j <- cites[1:66,1:5]
j$n <- 1
journals <- aggregate(j[,"n"], by=list(j[,"JOURNAL"]), FUN = sum)
q <- ggplot(journals, aes(x= Group.1, y = x))
 q + geom_lollipop(aes(reorder( Group.1, -x)),color = "orangered", cex=1) +
  coord_flip() +
  labs(x="Journal", y="Number of articles in the corpus")

rownames(cites_within) <- cites_within$REFID
cites_within$REFID <- NULL
cmat <- t(as.matrix(cites_within))
c <- colSums(cmat)
co <- c[order(-c)]
ref <- names(co)
cope <- data.frame(ref, co)
cope_full_names <- data.frame(cope, cites[match(cope$ref, cites$REFID),c("AUTHOR", "YEAR", "JOURNAL")])
cope_full_names$ref <- paste(cope_full_names$AUTHOR, cope_full_names$YEAR, sep=" ")

par(mar = c(2,2,2,2))
q <- ggplot(cope_full_names, aes(x=ref, y = cop))
q + geom_lollipop(aes(reorder(ref, -cop)),color = "seagreen3", cex=1) +
  coord_flip() +
  labs(x="Reference", y="Number of in-citations from the corpus")

age_journals <- data.frame(aggregate(j[,"YEAR"], by=list(j[,"JOURNAL"]), FUN = mean), journals$x)
age_disciplines <- data.frame(aggregate(j[,"YEAR"], by=list(j[,"DISCIPLINE"]), FUN = mean), disciplines$x)
rownames(age_disciplines) = age_disciplines$Group.1
rownames(age_journals) = age_journals$Group.1
age_disciplines$Group.1 <- NULL
age_journals$Group.1 <- NULL
colnames(age_disciplines) <- c("mean age", "n articles")
colnames(age_journals) <- c("mean age", "n articles")
round(mean(j$YEAR), digit=0)
[1] 2004
round(age_disciplines, digit=0)
corpussummary <- data.frame(j, cope[match(j$REFID, cope$ref),])
colnames(corpussummary)[8] <- "in_citations"
mean(corpussummary[corpussummary$in_citations > 10, "YEAR"])
[1] 1998.3

External citation analysis

cites_out <- cites[67:1221,]
cites_out$n_cites <- rowSums(cites_out[,6:71])
single_outcites <- cites_out[order(-cites_out$n_cites),c(1:5,72)] 
s_outcites <- single_outcites[,c("REFID", "n_cites")]
colnames(s_outcites) <- c("ref", "n")
s_outcites <- subset(s_outcites[-100,], n>=5)
q <- ggplot(s_outcites, aes(x=ref, y = n))
q + geom_lollipop(aes(reorder(ref, -n)),color = "coral3", cex=1) +
  coord_flip() +
  labs(x="Reference", y="Number of citations from the corpus (>=5)")

Who cited Nitsch (2005)?

who <- cites_out[cites_out$REFID == "Nitsch_2005_Journal_Urban_Economics",6:71]
who[1,]

Who did not cite G. K. Zipf himself?

nozipf<- as.data.frame(colSums(cites_out[cites_out$REFID %in% c("Zipf_1941_Unity_disunity",
                                                                "Zipf_1949_Human_Behavior_Principle_Least_Effort"),6:71]))
colnames(nozipf) <- "ref_zipf"
nozipf$ref_zipf <- ifelse(nozipf$ref_zipf == 0 , "no ref to zipf", "ref to zipf")
nozipf$REFID <- rownames(nozipf)
cites_for_ref_zipfs <- cites[1:66,]
referencing_zipf <- data.frame(cites_for_ref_zipfs, nozipf[match(cites_for_ref_zipfs$REFID, nozipf$REFID),])
rfczpf <- referencing_zipf[,c("YEAR", "DISCIPLINE", "ref_zipf")]

q <- ggplot(rfczpf, aes(x=YEAR))
q + geom_histogram(aes(y = stat(density), color = ref_zipf, fill = ref_zipf), 
                   alpha = 0.4, position = "identity", binwidth = 1) +
  geom_density(aes(color = ref_zipf), size = 1) +
  scale_color_manual(values = c("Coral2", "dodgerblue3")) +
scale_fill_manual(values = c("Coral2", "dodgerblue3"))  + labs(color = "") + guides(fill = FALSE, size = FALSE)+ theme(legend.position = "top")

table(rfczpf$ref_zipf, rfczpf$DISCIPLINE)
                
                    ECO GEO PHY REG OTHER STAT
  no ref to zipf  0  11   5   0  10     0    0
  ref to zipf     0  12   8   4  16     0    0

Which are the authors cited from Urban Studies?

cites_out[cites_out$JOURNAL == "Urban Studies","AUTHOR"]
 [1] Alperovich                     Batten                         Begg                           Bergsman Greenston Healy      
 [5] Boddy                          Chen Fu Zhang                  Cheshire Carbonaro             Clark Stabler                 
 [9] Ettlinger                      Garmestani Allen Gallagher al  Garmestani Allen Gallagher al  Hsu                           
[13] Huzinec                        Kuiper Kuiper Paelink          Lanaspa Pueyo Sans             Lipshitz                      
[17] Marshall                       Ogawa                          Parr                           Parr Suzuki                   
[21] Resende                        SuarezVilla                    Thompson                       VonBoventer                   
[25] Xu Zhu                         Zhao Zhang                     <NA>                          
987 Levels:  Alperovich G. Amalraj V. C. & Subbarayan A. Anderson G. & Ge Y. Aragon J. A. O. & Queiroz V. Arribas-Bel D. et al. ... Zipf 

Size of bibliography of corpus articles

n_citations <- as.data.frame(colSums(cites_out[,6:71], na.rm=T))
colnames(n_citations) <- "n_citations"
n_citations$REFID <- rownames(n_citations)
n_citations_corpus <- data.frame(cites_for_ref_zipfs, n_citations[match(cites_for_ref_zipfs$REFID, n_citations$REFID),])
n_citations_corpus$ref <- paste(n_citations_corpus$AUTHOR, n_citations_corpus$YEAR, sep=" ")

q <- ggplot(n_citations_corpus, aes(x=ref, y = n_citations))
q + geom_lollipop(aes(reorder(ref, -n_citations)),color = "dodgerblue3", cex=1) +
  coord_flip() +
  labs(x="Reference", y="Size of bibliography by corpus article")

Most cited external aticles

jou_out <- as.data.frame(table(cites_out$JOURNAL))
jou_out <- jou_out[order(-jou_out$Freq),] 
colnames(jou_out) <- c("ref", "n")
jou <- subset(jou_out[-100,], n>=5)
q <- ggplot(jou, aes(x=ref, y = n))
q + geom_lollipop(aes(reorder(ref, -n)),color = "goldenrod3", cex=1) +
  coord_flip() +
  labs(x="Journal", y="Number of citations from the corpus (>=5)")

Construction of the citation similarity network

outcitemat <- as.matrix(cites_out[,6:71])
toutcitemat <- t(outcitemat)
refSim <- rownames(toutcitemat)
cosSim <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
    k <- k + 1
    cosSim[k,1] <- i
    cosSim[k,2] <- j
    vi <- toutcitemat[i,]
    vj <- toutcitemat[j,]
    cosSim[k,3] <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
    }
  }
}
colnames(cosSim) <- c('i', 'j', 'cosSim')
write.csv(cosSim[order(-cosSim$cosSim),], "simNets/SimilarCitations.csv")

summary(cosSim$cosSim)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
0.00000 0.00000 0.04550 0.06399 0.10020 0.48670 
cs.cit <- cosSim[cosSim$cosSim >= 0.25,]
g.cit <- graph_from_data_frame(cs.cit, directed=F)

citingNs <- as.data.frame(apply(toutcitemat[rownames(toutcitemat) %in% V(g.cit)$name,],1, FUN = norm_vec))
colnames(citingNs) <- "citingN"
citingNs$ref <- rownames(citingNs)
orderedName <- data.frame(V(g.cit)$name)
citingN <- data.frame(orderedName, citingNs[match(orderedName$V.g.cit..name, citingNs$ref),])[,"citingN"]
citingN <- citingN[!is.na(citingN)] 

par(mar = c(0,0,0,0))
clln.cit <- cluster_louvain(g.cit)
layout <- layout_nicely(g.cit,2)
g.cit$layout <- layout
plot(g.cit, edge.width = sqrt(cs.cit$cosSim) * 2, vertex.size = citingN,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.cit))

Construction of the discipline similarity network

discipline2ref <- aggregate(cites_out[,c(6:71)], by=list(cites_out$DISCIPLINE), FUN = sumNum)
rownames(discipline2ref) <- discipline2ref$Group.1
discipline2ref$Group.1 <- NULL
cols <- colnames(discipline2ref)
for(i in cols){
  absolute <- discipline2ref[,i]
  total <- sum(absolute)
  relative <- absolute/total
  discipline2ref[,paste0("freq_",i)] <- relative
}

disc2ref <- as.matrix(discipline2ref[,67:132])
colnames(disc2ref) <- cols
scaled_disc2ref <- disc2ref / colSums(disc2ref)
tdisc2ref <- t(disc2ref)

refSim <- rownames(tdisc2ref)
cosSim <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      cosSim[k,1] <- i
      cosSim[k,2] <- j
      vi <- tdisc2ref[i,]
      vj <- tdisc2ref[j,]
      cosSim[k,3] <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
    }
  }
}
colnames(cosSim) <- c('i', 'j', 'cosSim')
write.csv(cosSim[order(-cosSim$cosSim),], "simNets/SimilarDisciplinesCited_rel.csv")
summary(cosSim$cosSim)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
0.07909 0.61930 0.79130 0.73710 0.88950 0.99690 
cs.cit <- cosSim[cosSim$cosSim >= 0.9,]
g.cit <- graph_from_data_frame(cs.cit, directed=F)

disCitedNs <- as.data.frame(apply(toutcitemat[rownames(tdisc2ref) %in% V(g.cit)$name,],1, FUN = norm_vec))
colnames(disCitedNs) <- "disCitedNs"
disCitedNs$ref <- rownames(disCitedNs)
orderedName <- data.frame(V(g.cit)$name)
disCitedNs <- data.frame(orderedName, disCitedNs[match(orderedName$V.g.cit..name, disCitedNs$ref),])[,"disCitedNs"]
disCitedNs <- disCitedNs[!is.na(disCitedNs)] 

colnames(orderedName) <- "REFID"
refinfo <- cites[1:66,c("REFID", "DISCIPLINE")]
own_discipline <- data.frame(orderedName, refinfo[match(orderedName$REFID, refinfo$REFID),])
odisc <- own_discipline$DISCIPLINE

layout <- layout_nicely(g.cit,2)
g.cit$layout <- layout
par(mar = c(0,0,0,0))
plot(g.cit, edge.width = sqrt(cs.cit$cosSim) * 2, vertex.size = disCitedNs,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = odisc)

Construction of full-text similarity network

docs <- tm_map(docs, toSpace, "-")
docs <- tm_map(docs, toSpace, ":")
docs <- tm_map(docs, toSpace, "'")
docs <- tm_map(docs, toSpace, "`")
docs <- tm_map(docs, toSpace, "‘")
docs <- tm_map(docs, toSpace, "_")
docs <- tm_map(docs, toSpace, "–")
docs <- tm_map(docs, toSpace, "/")
docs <- tm_map(docs, removePunctuation)
docs <- tm_map(docs, tolower)   
docs <- tm_map(docs, removeNumbers)   
docs <- tm_map(docs, removeWords, stopwords("english"))   
dtm <- DocumentTermMatrix(docs)   
dtm.m = as.matrix(dtm)
tdm <- TermDocumentMatrix(docs)   
tdm.m = as.matrix(tdm)

 tdm.df = as.data.frame(tdm.m)
 tdm.df.f <- tdm.df / colSums(tdm.df)

n_words <- as.data.frame(colSums(tdm.df, na.rm=T))
 colnames(n_words) <- "n_words"
 n_words$REFID <- substr(rownames(n_words), 1,8)
 n_words_corpus <- data.frame(cites_for_ref_zipfs, n_words[match(cites_for_ref_zipfs$REFID, n_words$REFID),])
 n_words_corpus$ref <- paste(n_words_corpus$AUTHOR, n_words_corpus$YEAR, sep=" ")
 n_words_corpus <- n_words_corpus[n_words_corpus$AUTHOR != "Krakover S.",]
 q <- ggplot(n_words_corpus, aes(x=ref, y = n_words))
 q + geom_lollipop(aes(reorder(ref, -n_words)),color = "seagreen4", cex=1) +
   coord_flip() +
   labs(x="Reference", y="Number of words by corpus article")

 termmat <- t(as.matrix(tdm.df.f))
 
 refSimTerm <- rownames(termmat)
 cosSimTerm <- data.frame()
 k=0
 ilist <- c()
 for(i in refSimTerm){
   ilist <- c(ilist, i)
   for(j in refSimTerm){
     if (j %!in% ilist){
       k <- k + 1
       cosSimTerm[k,1] <- i
       cosSimTerm[k,2] <- j
       vi <- termmat[i,]
       vj <- termmat[j,]
       cosSimTerm[k,3] <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
     }
   }
 }
 colnames(cosSimTerm) <- c('i', 'j', 'cosSimTerm')
 write.csv(cosSimTerm[order(-cosSimTerm$cosSimTerm),], "simNets/SimilarWording.csv")
 summary(cosSimTerm)
      i                  j               cosSimTerm    
 Length:2145        Length:2145        Min.   :0.1229  
 Class :character   Class :character   1st Qu.:0.3685  
 Mode  :character   Mode  :character   Median :0.4741  
                                       Mean   :0.4747  
                                       3rd Qu.:0.5777  
                                       Max.   :0.8728  
 cs <- cosSimTerm[cosSimTerm$cosSimTerm > 0.7,]
 g.term <- graph_from_data_frame(cs, directed=F)
 totalTerm <- as.data.frame(apply(termmat[rownames(termmat) %in% V(g.term)$name,],1, FUN = norm_vec))
 colnames(totalTerm) <- "totalTerms"
 totalTerm$ref <- rownames(totalTerm)
 orderedName <- data.frame(V(g.term)$name)
 totalTerms <- data.frame(orderedName, totalTerm[match(orderedName$V.g.term..name, totalTerm$ref),])[,"totalTerms"]
 totalTerms <- totalTerms[!is.na(totalTerms)] 
 clln.term <- cluster_louvain(g.term)
 layout <- layout_nicely(g.term,2)
 g.term$layout <- layout
 par(mar = c(0,0,0,0))
 plot(g.term, edge.width = sqrt(cs$cosSimTerm) * 2, vertex.size = totalTerms *50,
      vertex.label.cex = 0.7,  
      edge.curved=.2, vertex.color = membership(clln.term))

Construction country similarity network

  paperList <- colnames(cites_out[,6:71])
  countryData <- data[data$TERRITORY_TYPE == "Country" & data$REFID %in% paperList,]
country2Ref <- table(countryData$CNTR_ID, countryData$REFID)[-1,]
country2Ref.mat <- as.matrix(country2Ref[rowSums(country2Ref)>0,colnames(country2Ref) %in% paperList])
country2Ref.mat[country2Ref.mat>0] <- 1
countrymat <- t(country2Ref.mat)

refSim <- rownames(countrymat)
cosSimC <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      cosSimC[k,1] <- i
      cosSimC[k,2] <- j
      vi <- countrymat[i,]
      vj <- countrymat[j,]
      s <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
      cosSimC[k,3] <- ifelse(!is.na(s), s, 0)
    }
  }
}
colnames(cosSimC) <- c('i', 'j', 'cosSimC')
write.csv(cosSimC[order(-cosSimC$cosSimC),], "simNets/SimilarCountries.csv")
summary(cosSimC)
      i                  j                cosSimC       
 Length:2080        Length:2080        Min.   :0.00000  
 Class :character   Class :character   1st Qu.:0.00000  
 Mode  :character   Mode  :character   Median :0.00000  
                                       Mean   :0.09676  
                                       3rd Qu.:0.00000  
                                       Max.   :1.00000  
cs.cntr <- cosSimC[cosSimC$cosSimC >= 0.2,]
g.cntr <- graph_from_data_frame(cs.cntr, directed=F)
countryN <- as.data.frame(apply(countrymat[rownames(countrymat) %in% V(g.cntr)$name,],1, FUN = norm_vec))
colnames(countryN) <- "n_countries"
countryN$ref <- rownames(countryN)
orderedName <- data.frame(V(g.cntr)$name)
orderedCountryN <- data.frame(orderedName, countryN[match(orderedName$V.g.cntr..name, countryN$ref),])[,"n_countries"]
orderedCountryN <- orderedCountryN[!is.na(orderedCountryN)] 
clln.cntr <- cluster_louvain(g.cntr)
layout <- layout_nicely(g.cntr,2)
g.cntr$layout <- layout
 par(mar = c(0,0,0,0))
 plot(g.cntr, edge.width = sqrt(cs.cntr$cosSimC) * 2, vertex.size = orderedCountryN * 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.cntr))

Construction city definition similarity network

cityData <- data[!is.na(data$URBANSCALE) & data$REFID %in% paperList,]
city2Ref <- table(cityData$URBANSCALE, cityData$REFID)[,]
city2Ref.mat <- as.matrix(city2Ref[rowSums(city2Ref)>0,colnames(city2Ref) %in% paperList])
city2Ref.mat[city2Ref.mat>0] <- 1
citymat <- t(city2Ref.mat)

refSim <- rownames(citymat)
cosSimCt <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      cosSimCt[k,1] <- i
      cosSimCt[k,2] <- j
      vi <- citymat[i,]
      vj <- citymat[j,]
      s <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
      cosSimCt[k,3] <- ifelse(!is.na(s), s, 0)
    }
  }
}
colnames(cosSimCt) <- c('i', 'j', 'cosSimCt')
write.csv(cosSimCt[order(-cosSimCt$cosSimCt),], "simNets/SimilarCities.csv")
summary(cosSimCt)
      i                  j                cosSimCt     
 Length:2080        Length:2080        Min.   :0.0000  
 Class :character   Class :character   1st Qu.:0.0000  
 Mode  :character   Mode  :character   Median :0.0000  
                                       Mean   :0.4247  
                                       3rd Qu.:1.0000  
                                       Max.   :1.0000  
cs.city <- cosSimCt[cosSimCt$cosSimCt >= 0.1,]

g.city <- graph_from_data_frame(cs.city, directed=F)
cityN <- as.data.frame(apply(citymat[rownames(citymat) %in% V(g.city)$name,],1, FUN = norm_vec))
colnames(cityN) <- "n_cities"
cityN$ref <- rownames(cityN)
orderedName <- data.frame(V(g.city)$name)
orderedcityN <- data.frame(orderedName, cityN[match(orderedName$V.g.city..name, cityN$ref),])[,"n_cities"]
orderedcityN <- orderedcityN[!is.na(orderedcityN)] 

clln.city <- cluster_louvain(g.city)
layout <- layout_nicely(g.city,2)
g.city$layout <- layout
 par(mar = c(0,0,0,0))
 plot(g.city, edge.width = sqrt(cs.city$cosSimCt) * 2, vertex.size = orderedcityN * 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.city))

Construction decade similarity network

decadeData <- data[!is.na(data$DATE) & data$REFID %in% paperList,]
decadeData$DECADE <- paste0(substr(as.character(decadeData$DATE), 1, 3), 0, "s")
decade2Ref <- table(decadeData$DECADE, decadeData$REFID)[,]
decade2Ref.mat <- as.matrix(decade2Ref[rowSums(decade2Ref)>0,colnames(decade2Ref) %in% paperList])
decade2Ref.mat[decade2Ref.mat>0] <- 1
decademat <- t(decade2Ref.mat)

refSim <- rownames(decademat)
cosSimCt <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      cosSimCt[k,1] <- i
      cosSimCt[k,2] <- j
      vi <- decademat[i,]
      vj <- decademat[j,]
      s <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj))
      cosSimCt[k,3] <- ifelse(!is.na(s), s, 0)
    }
  }
}
colnames(cosSimCt) <- c('i', 'j', 'cosSimCt')
write.csv(cosSimCt[order(-cosSimCt$cosSimCt),], "simNets/SimilarDecades.csv")
summary(cosSimCt$cosSimCt)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.0000  0.3780  0.3639  0.5774  1.0000 
cs.decade <- cosSimCt[cosSimCt$cosSimCt >= 0.65,]

g.decade <- graph_from_data_frame(cs.decade, directed=F)
decadeN <- as.data.frame(apply(decademat[rownames(decademat) %in% V(g.decade)$name,],1, FUN = norm_vec))
colnames(decadeN) <- "n_decades"
decadeN$ref <- rownames(decadeN)
orderedName <- data.frame(V(g.decade)$name)
ordereddecadeN <- data.frame(orderedName, decadeN[match(orderedName$V.g.decade..name, decadeN$ref),])[,"n_decades"]
ordereddecadeN <- ordereddecadeN[!is.na(ordereddecadeN)]

clln.decade <- cluster_louvain(g.decade)
layout <- layout_nicely(g.decade,2)
g.decade$layout <- layout
par(mar = c(0,0,0,0))
plot(g.decade, edge.width = sqrt(cs.decade$cosSimCt) * 2, vertex.size = ordereddecadeN * 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.decade))

Construction of the networks of alpha similarity

alphaData <- data[!is.na(data$ALPHALOTKA) & data$REFID %in% paperList,]
alphaData$n <- 1
meanAlphaPerRef <- aggregate(alphaData[,"ALPHALOTKA"], by=list(alphaData$REFID), FUN=meanNum)
sdAlphaPerRef <- aggregate(alphaData[,"ALPHALOTKA"], by=list(alphaData$REFID), FUN=sdNum)
sdAlphaPerRef[is.na(sdAlphaPerRef$x),"x"] <- 0
nAlphaPerRef <- aggregate(alphaData[,"n"], by=list(alphaData$REFID), FUN=sumNum)

similarAlpha <- cbind(meanAlphaPerRef, sdAlphaPerRef, nAlphaPerRef)
rownames(similarAlpha) <- similarAlpha$Group.1
similarAlpha[,c(1,3, 5)] <- NULL
colnames(similarAlpha) <- c("meanAlpha", "sdAlpha", "nAlpha")

alphamat <- as.matrix(similarAlpha)

meanData <- mean(alphaData[,"ALPHALOTKA"])
sdData <- sd(alphaData[,"ALPHALOTKA"])
meanN <- mean(similarAlpha$nAlpha)

refSim <- rownames(alphamat)
diff_mean <- data.frame()
diff_sd <- data.frame()
diff_n <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      diff_mean[k,1] <- i
      diff_mean[k,2] <- j
      mi <- similarAlpha[i,1]
      mj <- similarAlpha[j,1]
      m <- abs((mi - mj) / meanData)
      diff_mean[k,3] <- m
      
      diff_sd[k,1] <- i
      diff_sd[k,2] <- j
      sdi <-similarAlpha[i,2]
      sdj <- similarAlpha[j,2]
      sd <- abs((sdi - sdj) / sdData)
      diff_sd[k,3] <- sd
      
      diff_n[k,1] <- i
      diff_n[k,2] <- j
      ni <-similarAlpha[i,3]
      nj <- similarAlpha[j,3]
      n <- abs((ni - nj) / meanN)
      diff_n[k,3] <- n
    }
  }
}

colnames(diff_mean) <- c('i', 'j', 'diff_mean')
write.csv(diff_mean[order(diff_mean$diff_mean),], "simNets/diff_mean.csv")
summary(diff_mean$diff_mean)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
0.0003241 0.0773200 0.1593000 0.2142000 0.2773000 1.2080000 
colnames(diff_sd) <- c('i', 'j', 'diff_sd')
write.csv(diff_sd[order(diff_sd$diff_sd),], "simNets/diff_sd.csv")
summary(diff_sd$diff_sd)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.1345  0.3152  0.4388  0.5466  3.1350 
colnames(diff_n) <- c('i', 'j', 'diff_n')
write.csv(diff_n[order(diff_n$diff_n),], "simNets/diff_n.csv")
summary(diff_n$diff_n)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.2305  0.6454  1.2150  1.3830  9.0820 

Similarity of mean alpha

cs.alpha <- diff_mean[diff_mean$diff_mean < 0.025,]
g.alpha <- graph_from_data_frame(cs.alpha, directed=F)
alphaM <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.alpha)$name,],1, FUN = norm_vec))
colnames(alphaM) <- "mean_alphas"
alphaM$ref <- rownames(alphaM)
orderedName <- data.frame(V(g.alpha)$name)
orderedalphaM <- data.frame(orderedName, alphaM[match(orderedName$V.g.alpha..name, alphaM$ref),])[,"mean_alphas"]
orderedalphaM <- orderedalphaM[!is.na(orderedalphaM)]
similarAlpha$REFID <- rownames(similarAlpha)
clln.alpha <- cluster_louvain(g.alpha)
layout <- layout_nicely(g.alpha,2)
g.alpha$layout <- layout

memb <- as.list(membership(clln.alpha))

vertexData <- data.frame(orderedREFID= names(membership(clln.alpha)))
vertexData <- data.frame(vertexData, similarAlpha[match(vertexData$orderedREFID, similarAlpha$REFID),])

for (r in vertexData$REFID){
  vertexData[vertexData$REFID == r,"memb_mean"] <- memb[r]
}

par(mar = c(0,0,0,0))
plot(g.alpha, edge.width = sqrt(cs.alpha$diff_mean) * 2, vertex.size = vertexData$meanAlpha^2 * 5,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.alpha))

# mean average value of alpha reported by group
aggregate(vertexData[,"meanAlpha"], by=list(vertexData$memb_mean), FUN=meanNum)

Similarity of sd alpha

cs.alpha <- diff_sd[diff_sd$diff_sd < 0.1,]
g.alpha <- graph_from_data_frame(cs.alpha, directed=F)
alphaSD <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.alpha)$name,],1, FUN = norm_vec))
colnames(alphaSD) <- "mean_sds"
alphaSD$ref <- rownames(alphaSD)
orderedName <- data.frame(V(g.alpha)$name)
orderedalphaSD <- data.frame(orderedName, alphaSD[match(orderedName$V.g.alpha..name, alphaSD$ref),])[,"mean_sds"]
orderedalphaSD <- orderedalphaSD[!is.na(orderedalphaSD)]

clln.alpha <- cluster_louvain(g.alpha)
layout <- layout_nicely(g.alpha,2)
g.alpha$layout <- layout

memb <- as.list(membership(clln.alpha))

vertexData <- data.frame(orderedREFID= names(membership(clln.alpha)))
vertexData <- data.frame(vertexData, similarAlpha[match(vertexData$orderedREFID, similarAlpha$REFID),])

for (r in vertexData$REFID){
  vertexData[vertexData$REFID == r,"memb_sd"] <- memb[r]
}

par(mar = c(0,0,0,0))
plot(g.alpha, edge.width = sqrt(cs.alpha$diff_sd) * 2, vertex.size = vertexData$sdAlpha * 50,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.alpha))

# mean average value of alpha reported by group
aggregate(vertexData[,"sdAlpha"], by=list(vertexData$memb_sd), FUN=meanNum)

Similarity of n alpha

cs.alpha <- diff_n[diff_n$diff_n < 0.1,]
g.alpha <- graph_from_data_frame(cs.alpha, directed=F)
alphaN <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.alpha)$name,],1, FUN = norm_vec))
colnames(alphaN) <- "mean_ns"
alphaN$ref <- rownames(alphaN)
orderedName <- data.frame(V(g.alpha)$name)
orderedalphaN <- data.frame(orderedName, alphaN[match(orderedName$V.g.alpha..name, alphaN$ref),])[,"mean_ns"]
orderedalphaN <- orderedalphaN[!is.na(orderedalphaN)]

clln.alpha <- cluster_louvain(g.alpha)
layout <- layout_nicely(g.alpha,2)
g.alpha$layout <- layout

memb <- as.list(membership(clln.alpha))

vertexData <- data.frame(orderedREFID= names(membership(clln.alpha)))
vertexData <- data.frame(vertexData, similarAlpha[match(vertexData$orderedREFID, similarAlpha$REFID),])

for (r in vertexData$REFID){
  vertexData[vertexData$REFID == r,"memb_n"] <- memb[r]
}

par(mar = c(0,0,0,0))
plot(g.alpha, edge.width = sqrt(cs.alpha$diff_n) * 2, vertex.size = vertexData$nAlpha * 0.4,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.alpha))

# mean average value of alpha reported by group
aggregate(vertexData[,"nAlpha"], by=list(vertexData$memb_n), FUN=meanNum)

Regression models of similarity in mean and sd alpha

Preparation of data

# import diff in alpha means
meanAlphaDyads <- read.csv2("simNets/diff_mean.csv", sep=",", stringsAsFactors = F)[,-1]
meanAlphaDyads$dyadID <- paste(meanAlphaDyads$i, meanAlphaDyads$j, sep = "_")
meanAlphaDyads$meanAlphaSim <- -as.numeric(meanAlphaDyads$diff_mean)
meanAlphaDyads[,1:3] <- NULL
DYADS <- meanAlphaDyads
DYAD_ID_order <- DYADS$dyadID

# import diff in alpha sd
sdAlphaDyads <- read.csv2("simNets/diff_sd.csv", sep=",", stringsAsFactors = F)[,-1]
sdAlphaDyads$dyadIJ <- paste(substr(sdAlphaDyads$i, 1, 8), 
                             substr(sdAlphaDyads$j, 1, 8), sep = "_")
sdAlphaDyads$dyadJI <- paste(substr(sdAlphaDyads$i, 1, 8), 
                             substr(sdAlphaDyads$j, 1, 8), sep = "_")
sdAlphaDyads$dyadID <- ifelse(sdAlphaDyads$dyadIJ %in% DYAD_ID_order, sdAlphaDyads$dyadIJ, sdAlphaDyads$dyadJI)

sdAlphaDyads$sdAlphaSim <- -as.numeric(sdAlphaDyads$diff_sd)
sdAlphaDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, sdAlphaDyads[match(DYADS$dyadID, sdAlphaDyads$dyadID),"sdAlphaSim"])

# import diff in n alpha 
nAlphaDyads <- read.csv2("simNets/diff_n.csv", sep=",", stringsAsFactors = F)[,-1]
nAlphaDyads$dyadIJ <- paste(substr(nAlphaDyads$i, 1, 8), 
                             substr(nAlphaDyads$j, 1, 8), sep = "_")
nAlphaDyads$dyadJI <- paste(substr(nAlphaDyads$i, 1, 8), 
                             substr(nAlphaDyads$j, 1, 8), sep = "_")
nAlphaDyads$dyadID <- ifelse(nAlphaDyads$dyadIJ %in% DYAD_ID_order, nAlphaDyads$dyadIJ, nAlphaDyads$dyadJI)

nAlphaDyads$nAlphaSim <- -as.numeric(nAlphaDyads$diff_n)
nAlphaDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, nAlphaDyads[match(DYADS$dyadID, nAlphaDyads$dyadID),"nAlphaSim"])

# import similarity in wording as explanation
wordingDyads <- read.csv2("simNets/SimilarWording.csv", sep=",", stringsAsFactors = F)[,-1]
head(wordingDyads)
wordingDyads$dyadIJ <- paste(substr(wordingDyads$i, 1, 8), 
                             substr(wordingDyads$j, 1, 8), sep = "_")
wordingDyads$dyadJI <- paste(substr(wordingDyads$i, 1, 8), 
                             substr(wordingDyads$j, 1, 8), sep = "_")
wordingDyads$dyadID <- ifelse(wordingDyads$dyadIJ %in% DYAD_ID_order, wordingDyads$dyadIJ, wordingDyads$dyadJI)

wordingDyads$wordingCosSim <- as.numeric(wordingDyads$cosSimTerm)
wordingDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, wordingDyads[match(DYADS$dyadID, wordingDyads$dyadID),"wordingCosSim"])

# import similarity in citation as explanation
citationDyads <- read.csv2("simNets/SimilarCitations.csv", sep=",", stringsAsFactors = F)[,-1]
citationDyads$dyadIJ <- paste(citationDyads$i, citationDyads$j, sep = "_")
citationDyads$dyadJI <- paste(citationDyads$j, citationDyads$i, sep = "_")
citationDyads$dyadID <- ifelse(citationDyads$dyadIJ %in% DYAD_ID_order, citationDyads$dyadIJ, citationDyads$dyadJI)
citationDyads$citationCosSim <- as.numeric(citationDyads$cosSim)
citationDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, citationDyads[match(DYADS$dyadID, citationDyads$dyadID),"citationCosSim"])

# import similarity in discipline as explanation
disciplineDyads <- read.csv2("simNets/SimilarDisciplinesCited_rel.csv", sep=",", stringsAsFactors = F)[,-1]
disciplineDyads$dyadIJ <- paste(disciplineDyads$i, disciplineDyads$j, sep = "_")
disciplineDyads$dyadJI <- paste(disciplineDyads$j, disciplineDyads$i, sep = "_")
disciplineDyads$dyadID <- ifelse(disciplineDyads$dyadIJ %in% DYAD_ID_order, disciplineDyads$dyadIJ, disciplineDyads$dyadJI)
disciplineDyads$disciplineCosSim <- as.numeric(disciplineDyads$cosSim)
disciplineDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, disciplineDyads[match(DYADS$dyadID, disciplineDyads$dyadID),"disciplineCosSim"])

# import similarity in countries studied as control
countryDyads <- read.csv2("simNets/SimilarCountries.csv", sep=",", stringsAsFactors = F)[,-1]
countryDyads$dyadIJ <- paste(countryDyads$i, countryDyads$j, sep = "_")
countryDyads$dyadJI <- paste(countryDyads$j, countryDyads$i, sep = "_")
countryDyads$dyadID <- ifelse(countryDyads$dyadIJ %in% DYAD_ID_order, countryDyads$dyadIJ, countryDyads$dyadJI)
countryDyads$countryCosSim <- as.numeric(countryDyads$cosSimC)
countryDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, countryDyads[match(DYADS$dyadID, countryDyads$dyadID),"countryCosSim"])

# import similarity in decades studied as control
decadeDyads <- read.csv2("simNets/SimilarDecades.csv", sep=",", stringsAsFactors = F)[,-1]
decadeDyads$dyadIJ <- paste(decadeDyads$i, decadeDyads$j, sep = "_")
decadeDyads$dyadJI <- paste(decadeDyads$j, decadeDyads$i, sep = "_")
decadeDyads$dyadID <- ifelse(decadeDyads$dyadIJ %in% DYAD_ID_order, decadeDyads$dyadIJ, decadeDyads$dyadJI)
decadeDyads$decadeCosSim <- as.numeric(decadeDyads$cosSimCt)
decadeDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, decadeDyads[match(DYADS$dyadID, decadeDyads$dyadID),"decadeCosSim"])

# import similarity in city definition used as control
cityDefDyads <- read.csv2("simNets/SimilarCities.csv", sep=",", stringsAsFactors = F)[,-1]
cityDefDyads$dyadIJ <- paste(cityDefDyads$i, cityDefDyads$j, sep = "_")
cityDefDyads$dyadJI <- paste(cityDefDyads$j, cityDefDyads$i, sep = "_")
cityDefDyads$dyadID <- ifelse(cityDefDyads$dyadIJ %in% DYAD_ID_order, cityDefDyads$dyadIJ, cityDefDyads$dyadJI)
cityDefDyads$cityDefCosSim <- as.numeric(cityDefDyads$cosSimCt)
cityDefDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, cityDefDyads[match(DYADS$dyadID, cityDefDyads$dyadID),"cityDefCosSim"])

colnames(DYADS) <- c("dyadID","meanAlphaSim", "sdAlphaSim", "nAlphaSim", 
                     "fullTextCosSim", "externalCitationCosSim", "disciplineCitationCosSim",
                     "countriesCosSim", "decadesCosSim", "cityDefCosSim")

# scale all variables
DYADS$meanAlphaSim_scaled <- scale(DYADS$meanAlphaSim)
DYADS$sdAlphaSim_scaled <- scale(DYADS$sdAlphaSim)
DYADS$nAlphaSim_scaled <- scale(DYADS$nAlphaSim)
DYADS$fullTextCosSim_scaled <- scale(DYADS$fullTextCosSim)
DYADS$externalCitationCosSim_scaled <- scale(DYADS$externalCitationCosSim)
DYADS$disciplineCitationCosSim_scaled <- scale(DYADS$disciplineCitationCosSim)
DYADS$countriesCosSim_scaled <- scale(DYADS$countriesCosSim)
DYADS$decadesCosSim_scaled <- scale(DYADS$decadesCosSim)
DYADS$cityDefCosSim_scaled <- scale(DYADS$cityDefCosSim)

DYADSwithNA <- DYADS
DYADS <- DYADS[complete.cases(DYADS),]

modeldata<- DYADS[,c("dyadID","meanAlphaSim_scaled", "sdAlphaSim_scaled", "nAlphaSim_scaled",
                     "fullTextCosSim_scaled", "externalCitationCosSim_scaled", "disciplineCitationCosSim_scaled",
                     "countriesCosSim_scaled", "decadesCosSim_scaled", "cityDefCosSim_scaled")]
colnames(modeldata) <- c("ID", "alpha", "sd_alpha", "n_estim","text", "citation", "discipline", "country", "decade", "city")

Models of mean alpha

ftm_a <- lm(data = modeldata,
            formula = alpha ~ text,
            na.action = na.omit)
ecm_a <- lm(data = modeldata,
            formula = alpha ~ citation,
            na.action = na.omit)
dcm_a <- lm(data = modeldata,
            formula = alpha ~ discipline,
            na.action = na.omit)
ctrm_a <- lm(data = modeldata,
            formula = alpha ~ n_estim +
             country * decade * city,
            na.action = na.omit)
fullmodel_a <- lm(data = modeldata,
            formula = alpha ~ 
              text + citation + discipline + n_estim +
              country * decade * city,
            na.action = na.omit)

sgm<- stargazer(ftm_a, ecm_a, dcm_a,
          ctrm_a,
          fullmodel_a,
          type="text", out="model_comp_results_meanAlpha.html", font.size = "small", column.sep.width = "1pt")

=========================================================================================================================================
                                                                     Dependent variable:                                                 
                    ---------------------------------------------------------------------------------------------------------------------
                                                                            alpha                                                        
                             (1)                     (2)                    (3)                    (4)                     (5)           
-----------------------------------------------------------------------------------------------------------------------------------------
text                       0.048**                                                                                       0.050**         
                           (0.022)                                                                                       (0.023)         
                                                                                                                                         
citation                                          0.062***                                                               0.069***        
                                                   (0.022)                                                               (0.024)         
                                                                                                                                         
discipline                                                                0.043*                                          0.015          
                                                                          (0.022)                                        (0.024)         
                                                                                                                                         
n_estim                                                                                         -0.053**                 -0.046**        
                                                                                                 (0.022)                 (0.022)         
                                                                                                                                         
country                                                                                         0.063***                 0.063***        
                                                                                                 (0.023)                 (0.023)         
                                                                                                                                         
decade                                                                                          -0.100***               -0.123***        
                                                                                                 (0.022)                 (0.023)         
                                                                                                                                         
city                                                                                             -0.001                   -0.015         
                                                                                                 (0.022)                 (0.023)         
                                                                                                                                         
country:decade                                                                                   -0.014                   -0.013         
                                                                                                 (0.021)                 (0.021)         
                                                                                                                                         
country:city                                                                                     0.049**                 0.053**         
                                                                                                 (0.022)                 (0.022)         
                                                                                                                                         
decade:city                                                                                      0.037*                   0.038*         
                                                                                                 (0.022)                 (0.022)         
                                                                                                                                         
country:decade:city                                                                              -0.017                   -0.014         
                                                                                                 (0.021)                 (0.021)         
                                                                                                                                         
Constant                    0.015                   0.015                  0.015                  0.013                   0.012          
                           (0.022)                 (0.022)                (0.022)                (0.022)                 (0.022)         
                                                                                                                                         
-----------------------------------------------------------------------------------------------------------------------------------------
Observations                2,016                   2,016                  2,016                  2,016                   2,016          
R2                          0.002                   0.004                  0.002                  0.021                   0.030          
Adjusted R2                 0.002                   0.003                  0.001                  0.017                   0.025          
Residual Std. Error   1.003 (df = 2014)       1.003 (df = 2014)      1.004 (df = 2014)      0.996 (df = 2007)       0.992 (df = 2004)    
F Statistic         4.519** (df = 1; 2014) 7.799*** (df = 1; 2014) 3.682* (df = 1; 2014) 5.403*** (df = 8; 2007) 5.707*** (df = 11; 2004)
=========================================================================================================================================
Note:                                                                                                         *p<0.1; **p<0.05; ***p<0.01

Models of sd alpha

ftm_sd <- lm(data = modeldata,
            formula = sd_alpha ~ text,
            na.action = na.omit)
ecm_sd <- lm(data = modeldata,
            formula = sd_alpha ~ citation,
            na.action = na.omit)
dcm_sd <- lm(data = modeldata,
            formula = sd_alpha ~ discipline,
            na.action = na.omit)
 n_sd <- lm(data = modeldata,
             formula = sd_alpha ~ n_estim,
             na.action = na.omit)
ctrm_sd <- lm(data = modeldata,
             formula = sd_alpha ~ 
               country * decade * city,
             na.action = na.omit)
fullmodel_sd <- lm(data = modeldata,
                  formula = sd_alpha ~ 
                    text + citation + discipline + n_estim +
                    country * decade * city,
                  na.action = na.omit)

sgm<- stargazer(ftm_sd, ecm_sd, dcm_sd,n_sd,
                ctrm_sd,
                fullmodel_sd,
                type="text", out="model_comp_results_sdAlpha.html", font.size = "small", column.sep.width = "1pt")

=================================================================================================================================================================
                                                                                 Dependent variable:                                                             
                    ---------------------------------------------------------------------------------------------------------------------------------------------
                                                                                      sd_alpha                                                                   
                              (1)                    (2)                  (3)                    (4)                      (5)                      (6)           
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
text                        0.112***                                                                                                            0.116***         
                            (0.022)                                                                                                              (0.023)         
                                                                                                                                                                 
citation                                            -0.013                                                                                       -0.006          
                                                   (0.022)                                                                                       (0.024)         
                                                                                                                                                                 
discipline                                                               -0.004                                                                  -0.009          
                                                                        (0.022)                                                                  (0.024)         
                                                                                                                                                                 
n_estim                                                                                        0.134***                                         0.133***         
                                                                                               (0.022)                                           (0.022)         
                                                                                                                                                                 
country                                                                                                                -0.096***                -0.078***        
                                                                                                                        (0.023)                  (0.022)         
                                                                                                                                                                 
decade                                                                                                                 -0.077***                -0.076***        
                                                                                                                        (0.022)                  (0.023)         
                                                                                                                                                                 
city                                                                                                                   0.088***                 0.083***         
                                                                                                                        (0.022)                  (0.022)         
                                                                                                                                                                 
country:decade                                                                                                          0.041*                   0.042**         
                                                                                                                        (0.021)                  (0.021)         
                                                                                                                                                                 
country:city                                                                                                            0.050**                  0.051**         
                                                                                                                        (0.022)                  (0.022)         
                                                                                                                                                                 
decade:city                                                                                                             0.050**                  0.051**         
                                                                                                                        (0.022)                  (0.022)         
                                                                                                                                                                 
country:decade:city                                                                                                     -0.023                   -0.016          
                                                                                                                        (0.021)                  (0.021)         
                                                                                                                                                                 
Constant                     -0.009                 -0.009               -0.009                 -0.008                  -0.014                   -0.013          
                            (0.022)                (0.022)              (0.022)                (0.022)                  (0.022)                  (0.022)         
                                                                                                                                                                 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Observations                 2,016                  2,016                2,016                  2,016                    2,016                    2,016          
R2                           0.012                  0.0002              0.00002                 0.018                    0.027                    0.055          
Adjusted R2                  0.012                 -0.0003              -0.0005                 0.017                    0.023                    0.050          
Residual Std. Error    0.999 (df = 2014)      1.005 (df = 2014)    1.005 (df = 2014)      0.996 (df = 2014)        0.993 (df = 2008)        0.980 (df = 2004)    
F Statistic         25.463*** (df = 1; 2014) 0.336 (df = 1; 2014) 0.032 (df = 1; 2014) 36.782*** (df = 1; 2014) 7.818*** (df = 7; 2008) 10.685*** (df = 11; 2004)
=================================================================================================================================================================
Note:                                                                                                                                 *p<0.1; **p<0.05; ***p<0.01

Residuals analysis

modeldata$res <- fullmodel_a$residuals
head(modeldata[order(-modeldata$res),])
modeldata$i <- substr(modeldata$ID, 1,8)
modeldata$j <- substr(modeldata$ID, 10, 17)

cs.residuals_resPos <- modeldata[modeldata$res > 1.1,c("i", "j", "res")]
g.residuals <- graph_from_data_frame(cs.residuals_resPos, directed=F)
resPos <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.residuals)$name,],1, FUN = norm_vec))
colnames(resPos) <- "residuals"
resPos$ref <- rownames(resPos)
orderedName <- data.frame(V(g.residuals)$name)
orderedresidualsRes <- data.frame(orderedName, resPos[match(orderedName$V.g.residuals..name, resPos$ref),])[,"residuals"]
orderedresidualsRes <- orderedresidualsRes[!is.na(orderedresidualsRes)]

layout <- layout_nicely(g.residuals,2)
g.residuals$layout <- layout
par(mar = c(0,0,1,0))
plot(g.residuals, edge.width = sqrt(cs.residuals_resPos$res) * 2, vertex.size = 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = "green", edge.color = "coral3", 
     main = "Most positive residuals in mean alpha similarity")

cs.residuals_resNeg <- modeldata[modeldata$res < -2,c("i", "j", "res")]
g.residuals <- graph_from_data_frame(cs.residuals_resNeg, directed=F)
resNeg <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.residuals)$name,],1, FUN = norm_vec))
colnames(resNeg) <- "residuals"
resNeg$ref <- rownames(resNeg)
orderedName <- data.frame(V(g.residuals)$name)
orderedresidualsRes <- data.frame(orderedName, resNeg[match(orderedName$V.g.residuals..name, resNeg$ref),])[,"residuals"]
orderedresidualsRes <- orderedresidualsRes[!is.na(orderedresidualsRes)]

layout <- layout_nicely(g.residuals,2)
g.residuals$layout <- layout
par(mar = c(0,0,1,0))
plot(g.residuals, edge.width = sqrt(cs.residuals_resNeg$res) * 2, vertex.size = 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = "orange", edge.color = "dodgerblue3", 
     main = "Most negative residuals in mean alpha similarity")

modeldata$res <- fullmodel_sd$residuals
modeldata$i <- substr(modeldata$ID, 1,8)
modeldata$j <- substr(modeldata$ID, 10, 17)

cs.residuals_resPos <- modeldata[modeldata$res > 1,c("i", "j", "res")]
g.residuals <- graph_from_data_frame(cs.residuals_resPos, directed=F)
resPos <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.residuals)$name,],1, FUN = norm_vec))
colnames(resPos) <- "residuals"
resPos$ref <- rownames(resPos)
orderedName <- data.frame(V(g.residuals)$name)
orderedresidualsRes <- data.frame(orderedName, resPos[match(orderedName$V.g.residuals..name, resPos$ref),])[,"residuals"]
orderedresidualsRes <- orderedresidualsRes[!is.na(orderedresidualsRes)]

#clln.residuals <- cluster_louvain(g.residuals)
layout <- layout_nicely(g.residuals,2)
g.residuals$layout <- layout
par(mar = c(0,0,1,0))
plot(g.residuals, edge.width = sqrt(cs.residuals_resPos$res) * 2, vertex.size = 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = "green", edge.color = "coral3", 
     main = "Most positive residuals in sd alpha similarity")

cs.residuals_resNeg <- modeldata[modeldata$res < -1.5,c("i", "j", "res")]
g.residuals <- graph_from_data_frame(cs.residuals_resNeg, directed=F)
resNeg <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.residuals)$name,],1, FUN = norm_vec))
colnames(resNeg) <- "residuals"
resNeg$ref <- rownames(resNeg)
orderedName <- data.frame(V(g.residuals)$name)
orderedresidualsRes <- data.frame(orderedName, resNeg[match(orderedName$V.g.residuals..name, resNeg$ref),])[,"residuals"]
orderedresidualsRes <- orderedresidualsRes[!is.na(orderedresidualsRes)]

layout <- layout_nicely(g.residuals,2)
g.residuals$layout <- layout
par(mar = c(0,0,1,0))
plot(g.residuals, edge.width = sqrt(cs.residuals_resNeg$res) * 2, vertex.size = 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = "orange", edge.color = "dodgerblue3", 
     main = "Most negative residuals in sd alpha similarity")

LS0tCnRpdGxlOiAiVGhlIE1ldGFNZXRhWmlwZiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBSIE5vdGVib29rIHdoaWNoIHJlcHJvZHVjZXMgdGhlIGFuYWx5c2lzLCB0YWJsZXMgYW5kIGZpZ3VyZXMgb2YgdGhlIHdvcmtpbmcgcGFwZXIgIk1ldGFNZXRhWmlwZi4gV2hhdCBkbyBhbmFseXNlcyBvZiBjaXR5IHNpemUgZGlzdHJpYnV0aW9ucyBoYXZlIGluIGNvbW1vbj8iLiBUaGUgZGF0YSBpcyBzdG9yZWQgb24gdGhlIFtNZXRhWmlwZl0oaHR0cHM6Ly9naXRodWIuY29tL0NsZW1lbnRpbmVDdHRuL01ldGFaaXBmKSBHaXRIdWIgcmVwb3NpdG9yeS4KCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkoaWdyYXBoKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeSh3ZXNhbmRlcnNvbikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoZ2dhbHQpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeSh0bSkKbGlicmFyeShjbHVzdGVyKQpsaWJyYXJ5KFNub3diYWxsQykKbGlicmFyeShzdGFyZ2F6ZXIpCmxpYnJhcnkocmVzaGFwZTIpCgoKJyUhaW4lJyA8LSBmdW5jdGlvbih4LHkpISgnJWluJScoeCx5KSkKbm9ybV92ZWMgPC0gZnVuY3Rpb24oeCkgc3FydChzdW1OdW0oeF4yKSkKCnN1bU51bSA9IGZ1bmN0aW9uKHgpIHsgCiAgcyA9IHN1bSh4LCBuYS5ybSA9IFQpCiAgcmV0dXJuKHMpCn0KbWVhbk51bSA9IGZ1bmN0aW9uKHgpIHsgCiAgcyA9IG1lYW4oeCwgbmEucm0gPSBUKQogIHJldHVybihzKQp9CgpzZE51bSA9IGZ1bmN0aW9uKHgpIHsgCiAgcyA9IHNkKHgsIG5hLnJtID0gVCkKICByZXR1cm4ocykKfQoKdG9TcGFjZSA8LSBjb250ZW50X3RyYW5zZm9ybWVyKGZ1bmN0aW9uKHgsIHBhdHRlcm4pIHsKICByZXR1cm4gKGdzdWIocGF0dGVybiwgIiAiLCB4KSkKfSkKCnN0YXQuY29tcDwtICBmdW5jdGlvbiggeCx5KXsKICBLIDwtbGVuZ3RoKHVuaXF1ZSh5KSkKICBuIDwtbGVuZ3RoKHgpCiAgbSA8LW1lYW4oeCkKICBUU1MgPC1zdW0oKHgtbSleMikKICBuazwtdGFibGUoeSkKICBtazwtdGFwcGx5KHgseSxtZWFuKQogIEJTUyA8LXN1bShuayogKG1rLW0pXjIpCiAgcmVzdWx0PC1jKG1rLDEwMC4wKkJTUy9UU1MpCiAgbmFtZXMocmVzdWx0KSA8LWMoIHBhc3RlKCJHIiwxOkspLCIlIGVwbC4iKQogIHJldHVybihyZXN1bHQpCn0KCmBgYAoKCiMgSW1wb3J0aW5nIERhdGEgZnJvbSB0aGUgbWV0YVppcGYgcHJvamVjdDogCiogdGhlIGluZm9ybWF0aW9uIGFib3V0IGFydGljbGVzIGluIHRoZSBjb3JwdXMgKHJlZnMpCiogdGhlIGVtcGlyaWNhbCBlc3RpbWF0aW9ucyB0aGV5IHJlcG9ydCBhbG9uZyB3aXRoIHRoZWlyIHNwZWNpZmljYXRpb25zIChkYXRhKQoqIHRoZSBjaXRhdGlvbiBtYXRyaXggKGNpdGVzKQoqIHRoZSBjbGVhbmVkIGZ1bGwtdGV4dHMgKGRvY3MpCiogdGhlIGxvb2t1cCB0YWJsZSBmcm9tIGpvdXJuYWwgdG8gZGlzY2lwbGluZSAoSjJEKQoKYGBge3IgaW1wb3J0fQpyZWZzIDwtIHJlYWQuY3N2MigiZGF0YS96aXBmX3JlZnMuY3N2Iiwgc2VwPSc7JykKY2l0ZXMgPC0gcmVhZC5jc3YyKCJkYXRhL3ppcGZfY2l0ZXMuY3N2Iiwgc2VwPScsJykKZGF0YSA8LSByZWFkLmNzdjIoImRhdGEvemlwZl9tZXRhLmNzdiIsIHNlcD0iLCIsIGRlYz0iLiIpCmNuYW1lIDwtICJkYXRhL0Z1bGxUZXh0LyIKZG9jcyA8LSBDb3JwdXMoRGlyU291cmNlKGNuYW1lKSkgICAKSjJEIDwtIHJlYWQuY3N2Mignam91cm5hbHMyRGlzY2lwbGluZXMuY3N2Jywgc2VwPSc7JykKYGBgCgoKIyMgQ2xlYW5pbmcgY2l0YXRpb24gZGF0YQpgYGB7ciBjbGVhbkNpdGF0aW9uLCB3YXJuaW5nPUZBTFNFfQpjaXRlc19vdXQgPC0gY2l0ZXNbNjc6MTIyMSxdCmNpdGVzX291dCRZRUFSIDwtIGFzLm51bWVyaWMoZ3N1YigiXFxEKyIsICIiLCBjaXRlc19vdXQkUkVGSUQpKQpjaXRlc19vdXQkSk9VUk5BTCA8LSBnc3ViKCIuKlxcZC4iLCAiIiwgY2l0ZXNfb3V0JFJFRklEKQpjaXRlc19vdXQkQVVUSE9SIDwtIGdzdWIoIlxcZC4qIiwgIiIsIGNpdGVzX291dCRSRUZJRCkKY2l0ZXNfb3V0JEpPVVJOQUwgPC0gZ3N1YigiW1s6cHVuY3Q6XV0iLCAiICIsIGNpdGVzX291dCRKT1VSTkFMKQpjaXRlc19vdXQkQVVUSE9SIDwtIGdzdWIoIltbOnB1bmN0Ol1dIiwgIiAiLCBjaXRlc19vdXQkQVVUSE9SKQpjaXRlc19vdXQgPC0gZGF0YS5mcmFtZShjaXRlc19vdXQsSjJEW21hdGNoKGNpdGVzX291dCRKT1VSTkFMLCBKMkQkSk9VUk5BTCksXSkKY2l0ZXNfb3V0JERJU0NJUExJTkUgPC0gY2l0ZXNfb3V0JERJU0NQTElORQpjaXRlc19vdXQkRElTQ1BMSU5FIDwtIE5VTEwKY2l0ZXNfb3V0JEpPVVJOQUwuMSA8LSBOVUxMCmNpdGVzIDwtIHJiaW5kKGNpdGVzWzE6NjYsXSxjaXRlc19vdXQpCmNpdGVzW2lzLm5hKGNpdGVzKV0gPC0gMApjaXRlc193aXRoaW4gPC0gY2l0ZXNbMTo2NixjKDEsNjo3MSldCmhlYWQoY2l0ZXMpCmBgYAoKIyMgQ29ycHVzIGFuYWx5c2lzCgpgYGB7ciBjb3JwdXNBbmFseXNpc30KCmogPC0gY2l0ZXNbMTo2NiwxOjVdCmokbiA8LSAxCmpvdXJuYWxzIDwtIGFnZ3JlZ2F0ZShqWywibiJdLCBieT1saXN0KGpbLCJKT1VSTkFMIl0pLCBGVU4gPSBzdW0pCnEgPC0gZ2dwbG90KGpvdXJuYWxzLCBhZXMoeD0gR3JvdXAuMSwgeSA9IHgpKQogcSArIGdlb21fbG9sbGlwb3AoYWVzKHJlb3JkZXIoIEdyb3VwLjEsIC14KSksY29sb3IgPSAib3JhbmdlcmVkIiwgY2V4PTEpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoeD0iSm91cm5hbCIsIHk9Ik51bWJlciBvZiBhcnRpY2xlcyBpbiB0aGUgY29ycHVzIikKCnJvd25hbWVzKGNpdGVzX3dpdGhpbikgPC0gY2l0ZXNfd2l0aGluJFJFRklECmNpdGVzX3dpdGhpbiRSRUZJRCA8LSBOVUxMCmNtYXQgPC0gdChhcy5tYXRyaXgoY2l0ZXNfd2l0aGluKSkKYyA8LSBjb2xTdW1zKGNtYXQpCmNvIDwtIGNbb3JkZXIoLWMpXQpyZWYgPC0gbmFtZXMoY28pCmNvcGUgPC0gZGF0YS5mcmFtZShyZWYsIGNvKQpjb3BlX2Z1bGxfbmFtZXMgPC0gZGF0YS5mcmFtZShjb3BlLCBjaXRlc1ttYXRjaChjb3BlJHJlZiwgY2l0ZXMkUkVGSUQpLGMoIkFVVEhPUiIsICJZRUFSIiwgIkpPVVJOQUwiKV0pCmNvcGVfZnVsbF9uYW1lcyRyZWYgPC0gcGFzdGUoY29wZV9mdWxsX25hbWVzJEFVVEhPUiwgY29wZV9mdWxsX25hbWVzJFlFQVIsIHNlcD0iICIpCgpwYXIobWFyID0gYygyLDIsMiwyKSkKcSA8LSBnZ3Bsb3QoY29wZV9mdWxsX25hbWVzLCBhZXMoeD1yZWYsIHkgPSBjb3ApKQpxICsgZ2VvbV9sb2xsaXBvcChhZXMocmVvcmRlcihyZWYsIC1jb3ApKSxjb2xvciA9ICJzZWFncmVlbjMiLCBjZXg9MSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh4PSJSZWZlcmVuY2UiLCB5PSJOdW1iZXIgb2YgaW4tY2l0YXRpb25zIGZyb20gdGhlIGNvcnB1cyIpCgoKYWdlX2pvdXJuYWxzIDwtIGRhdGEuZnJhbWUoYWdncmVnYXRlKGpbLCJZRUFSIl0sIGJ5PWxpc3QoalssIkpPVVJOQUwiXSksIEZVTiA9IG1lYW4pLCBqb3VybmFscyR4KQphZ2VfZGlzY2lwbGluZXMgPC0gZGF0YS5mcmFtZShhZ2dyZWdhdGUoalssIllFQVIiXSwgYnk9bGlzdChqWywiRElTQ0lQTElORSJdKSwgRlVOID0gbWVhbiksIGRpc2NpcGxpbmVzJHgpCnJvd25hbWVzKGFnZV9kaXNjaXBsaW5lcykgPSBhZ2VfZGlzY2lwbGluZXMkR3JvdXAuMQpyb3duYW1lcyhhZ2Vfam91cm5hbHMpID0gYWdlX2pvdXJuYWxzJEdyb3VwLjEKYWdlX2Rpc2NpcGxpbmVzJEdyb3VwLjEgPC0gTlVMTAphZ2Vfam91cm5hbHMkR3JvdXAuMSA8LSBOVUxMCmNvbG5hbWVzKGFnZV9kaXNjaXBsaW5lcykgPC0gYygibWVhbiBhZ2UiLCAibiBhcnRpY2xlcyIpCmNvbG5hbWVzKGFnZV9qb3VybmFscykgPC0gYygibWVhbiBhZ2UiLCAibiBhcnRpY2xlcyIpCnJvdW5kKG1lYW4oaiRZRUFSKSwgZGlnaXQ9MCkKcm91bmQoYWdlX2Rpc2NpcGxpbmVzLCBkaWdpdD0wKQpjb3JwdXNzdW1tYXJ5IDwtIGRhdGEuZnJhbWUoaiwgY29wZVttYXRjaChqJFJFRklELCBjb3BlJHJlZiksXSkKY29sbmFtZXMoY29ycHVzc3VtbWFyeSlbOF0gPC0gImluX2NpdGF0aW9ucyIKbWVhbihjb3JwdXNzdW1tYXJ5W2NvcnB1c3N1bW1hcnkkaW5fY2l0YXRpb25zID4gMTAsICJZRUFSIl0pCmBgYAoKIyMgRXh0ZXJuYWwgY2l0YXRpb24gYW5hbHlzaXMKCmBgYHtyIGNpdGF0aW9uQW5hbHlzaXN9CmNpdGVzX291dCA8LSBjaXRlc1s2NzoxMjIxLF0KY2l0ZXNfb3V0JG5fY2l0ZXMgPC0gcm93U3VtcyhjaXRlc19vdXRbLDY6NzFdKQpzaW5nbGVfb3V0Y2l0ZXMgPC0gY2l0ZXNfb3V0W29yZGVyKC1jaXRlc19vdXQkbl9jaXRlcyksYygxOjUsNzIpXSAKc19vdXRjaXRlcyA8LSBzaW5nbGVfb3V0Y2l0ZXNbLGMoIlJFRklEIiwgIm5fY2l0ZXMiKV0KY29sbmFtZXMoc19vdXRjaXRlcykgPC0gYygicmVmIiwgIm4iKQpzX291dGNpdGVzIDwtIHN1YnNldChzX291dGNpdGVzWy0xMDAsXSwgbj49NSkKcSA8LSBnZ3Bsb3Qoc19vdXRjaXRlcywgYWVzKHg9cmVmLCB5ID0gbikpCnEgKyBnZW9tX2xvbGxpcG9wKGFlcyhyZW9yZGVyKHJlZiwgLW4pKSxjb2xvciA9ICJjb3JhbDMiLCBjZXg9MSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh4PSJSZWZlcmVuY2UiLCB5PSJOdW1iZXIgb2YgY2l0YXRpb25zIGZyb20gdGhlIGNvcnB1cyAoPj01KSIpCmBgYAoKV2hvIGNpdGVkIE5pdHNjaCAoMjAwNSk/CmBgYHtyIGV4YW1wbGVDaXRhdGlvbn0Kd2hvIDwtIGNpdGVzX291dFtjaXRlc19vdXQkUkVGSUQgPT0gIk5pdHNjaF8yMDA1X0pvdXJuYWxfVXJiYW5fRWNvbm9taWNzIiw2OjcxXQp3aG9bMSxdCmBgYAoKV2hvIGRpZCBub3QgY2l0ZSBHLiBLLiBaaXBmIGhpbXNlbGY/CmBgYHtyIG5vWmlwZkNpdGF0aW9ufQpub3ppcGY8LSBhcy5kYXRhLmZyYW1lKGNvbFN1bXMoY2l0ZXNfb3V0W2NpdGVzX291dCRSRUZJRCAlaW4lIGMoIlppcGZfMTk0MV9Vbml0eV9kaXN1bml0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiWmlwZl8xOTQ5X0h1bWFuX0JlaGF2aW9yX1ByaW5jaXBsZV9MZWFzdF9FZmZvcnQiKSw2OjcxXSkpCmNvbG5hbWVzKG5vemlwZikgPC0gInJlZl96aXBmIgpub3ppcGYkcmVmX3ppcGYgPC0gaWZlbHNlKG5vemlwZiRyZWZfemlwZiA9PSAwICwgIm5vIHJlZiB0byB6aXBmIiwgInJlZiB0byB6aXBmIikKbm96aXBmJFJFRklEIDwtIHJvd25hbWVzKG5vemlwZikKY2l0ZXNfZm9yX3JlZl96aXBmcyA8LSBjaXRlc1sxOjY2LF0KcmVmZXJlbmNpbmdfemlwZiA8LSBkYXRhLmZyYW1lKGNpdGVzX2Zvcl9yZWZfemlwZnMsIG5vemlwZlttYXRjaChjaXRlc19mb3JfcmVmX3ppcGZzJFJFRklELCBub3ppcGYkUkVGSUQpLF0pCnJmY3pwZiA8LSByZWZlcmVuY2luZ196aXBmWyxjKCJZRUFSIiwgIkRJU0NJUExJTkUiLCAicmVmX3ppcGYiKV0KCnEgPC0gZ2dwbG90KHJmY3pwZiwgYWVzKHg9WUVBUikpCnEgKyBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IHN0YXQoZGVuc2l0eSksIGNvbG9yID0gcmVmX3ppcGYsIGZpbGwgPSByZWZfemlwZiksIAogICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjQsIHBvc2l0aW9uID0gImlkZW50aXR5IiwgYmlud2lkdGggPSAxKSArCiAgZ2VvbV9kZW5zaXR5KGFlcyhjb2xvciA9IHJlZl96aXBmKSwgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiQ29yYWwyIiwgImRvZGdlcmJsdWUzIikpICsKc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiQ29yYWwyIiwgImRvZGdlcmJsdWUzIikpICArIGxhYnMoY29sb3IgPSAiIikgKyBndWlkZXMoZmlsbCA9IEZBTFNFLCBzaXplID0gRkFMU0UpKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCnRhYmxlKHJmY3pwZiRyZWZfemlwZiwgcmZjenBmJERJU0NJUExJTkUpCmBgYAoKV2hpY2ggYXJlIHRoZSBhdXRob3JzIGNpdGVkIGZyb20gVXJiYW4gU3R1ZGllcz8KYGBge3IgZXhDaXRhdGlvbkZyb21Kb3VybmFsfQpjaXRlc19vdXRbY2l0ZXNfb3V0JEpPVVJOQUwgPT0gIlVyYmFuIFN0dWRpZXMiLCJBVVRIT1IiXQpgYGAKClNpemUgb2YgYmlibGlvZ3JhcGh5IG9mIGNvcnB1cyBhcnRpY2xlcwpgYGB7ciBzaXplQmlibGlvfQpuX2NpdGF0aW9ucyA8LSBhcy5kYXRhLmZyYW1lKGNvbFN1bXMoY2l0ZXNfb3V0Wyw2OjcxXSwgbmEucm09VCkpCmNvbG5hbWVzKG5fY2l0YXRpb25zKSA8LSAibl9jaXRhdGlvbnMiCm5fY2l0YXRpb25zJFJFRklEIDwtIHJvd25hbWVzKG5fY2l0YXRpb25zKQpuX2NpdGF0aW9uc19jb3JwdXMgPC0gZGF0YS5mcmFtZShjaXRlc19mb3JfcmVmX3ppcGZzLCBuX2NpdGF0aW9uc1ttYXRjaChjaXRlc19mb3JfcmVmX3ppcGZzJFJFRklELCBuX2NpdGF0aW9ucyRSRUZJRCksXSkKbl9jaXRhdGlvbnNfY29ycHVzJHJlZiA8LSBwYXN0ZShuX2NpdGF0aW9uc19jb3JwdXMkQVVUSE9SLCBuX2NpdGF0aW9uc19jb3JwdXMkWUVBUiwgc2VwPSIgIikKCnEgPC0gZ2dwbG90KG5fY2l0YXRpb25zX2NvcnB1cywgYWVzKHg9cmVmLCB5ID0gbl9jaXRhdGlvbnMpKQpxICsgZ2VvbV9sb2xsaXBvcChhZXMocmVvcmRlcihyZWYsIC1uX2NpdGF0aW9ucykpLGNvbG9yID0gImRvZGdlcmJsdWUzIiwgY2V4PTEpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoeD0iUmVmZXJlbmNlIiwgeT0iU2l6ZSBvZiBiaWJsaW9ncmFwaHkgYnkgY29ycHVzIGFydGljbGUiKQoKYGBgCgpNb3N0IGNpdGVkIGV4dGVybmFsIGF0aWNsZXMKYGBge3IgTW9zdENpdGVkQXJ0aWNsZXN9Cgpqb3Vfb3V0IDwtIGFzLmRhdGEuZnJhbWUodGFibGUoY2l0ZXNfb3V0JEpPVVJOQUwpKQpqb3Vfb3V0IDwtIGpvdV9vdXRbb3JkZXIoLWpvdV9vdXQkRnJlcSksXSAKY29sbmFtZXMoam91X291dCkgPC0gYygicmVmIiwgIm4iKQpqb3UgPC0gc3Vic2V0KGpvdV9vdXRbLTEwMCxdLCBuPj01KQpxIDwtIGdncGxvdChqb3UsIGFlcyh4PXJlZiwgeSA9IG4pKQpxICsgZ2VvbV9sb2xsaXBvcChhZXMocmVvcmRlcihyZWYsIC1uKSksY29sb3IgPSAiZ29sZGVucm9kMyIsIGNleD0xKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKHg9IkpvdXJuYWwiLCB5PSJOdW1iZXIgb2YgY2l0YXRpb25zIGZyb20gdGhlIGNvcnB1cyAoPj01KSIpCmBgYAoKIyBDb25zdHJ1Y3Rpb24gb2YgdGhlIGNpdGF0aW9uIHNpbWlsYXJpdHkgbmV0d29yawpgYGB7ciBjaXRhdGlvblNpbWlsYXJpdHlOZXR3b3JrfQoKb3V0Y2l0ZW1hdCA8LSBhcy5tYXRyaXgoY2l0ZXNfb3V0Wyw2OjcxXSkKdG91dGNpdGVtYXQgPC0gdChvdXRjaXRlbWF0KQpyZWZTaW0gPC0gcm93bmFtZXModG91dGNpdGVtYXQpCmNvc1NpbSA8LSBkYXRhLmZyYW1lKCkKaz0wCmlsaXN0IDwtIGMoKQpmb3IoaSBpbiByZWZTaW0pewogIGlsaXN0IDwtIGMoaWxpc3QsIGkpCiAgZm9yKGogaW4gcmVmU2ltKXsKICAgIGlmIChqICUhaW4lIGlsaXN0KXsKICAgIGsgPC0gayArIDEKICAgIGNvc1NpbVtrLDFdIDwtIGkKICAgIGNvc1NpbVtrLDJdIDwtIGoKICAgIHZpIDwtIHRvdXRjaXRlbWF0W2ksXQogICAgdmogPC0gdG91dGNpdGVtYXRbaixdCiAgICBjb3NTaW1baywzXSA8LSAoc3VtTnVtKHZpICogdmopKSAvIChub3JtX3ZlYyh2aSkgKiAgbm9ybV92ZWModmopKSAKICAgIH0KICB9Cn0KY29sbmFtZXMoY29zU2ltKSA8LSBjKCdpJywgJ2onLCAnY29zU2ltJykKd3JpdGUuY3N2KGNvc1NpbVtvcmRlcigtY29zU2ltJGNvc1NpbSksXSwgInNpbU5ldHMvU2ltaWxhckNpdGF0aW9ucy5jc3YiKQoKc3VtbWFyeShjb3NTaW0kY29zU2ltKQpjcy5jaXQgPC0gY29zU2ltW2Nvc1NpbSRjb3NTaW0gPj0gMC4yNSxdCmcuY2l0IDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShjcy5jaXQsIGRpcmVjdGVkPUYpCgpjaXRpbmdOcyA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KHRvdXRjaXRlbWF0W3Jvd25hbWVzKHRvdXRjaXRlbWF0KSAlaW4lIFYoZy5jaXQpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKGNpdGluZ05zKSA8LSAiY2l0aW5nTiIKY2l0aW5nTnMkcmVmIDwtIHJvd25hbWVzKGNpdGluZ05zKQpvcmRlcmVkTmFtZSA8LSBkYXRhLmZyYW1lKFYoZy5jaXQpJG5hbWUpCmNpdGluZ04gPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgY2l0aW5nTnNbbWF0Y2gob3JkZXJlZE5hbWUkVi5nLmNpdC4ubmFtZSwgY2l0aW5nTnMkcmVmKSxdKVssImNpdGluZ04iXQpjaXRpbmdOIDwtIGNpdGluZ05bIWlzLm5hKGNpdGluZ04pXSAKCnBhcihtYXIgPSBjKDAsMCwwLDApKQpjbGxuLmNpdCA8LSBjbHVzdGVyX2xvdXZhaW4oZy5jaXQpCmxheW91dCA8LSBsYXlvdXRfbmljZWx5KGcuY2l0LDIpCmcuY2l0JGxheW91dCA8LSBsYXlvdXQKcGxvdChnLmNpdCwgZWRnZS53aWR0aCA9IHNxcnQoY3MuY2l0JGNvc1NpbSkgKiAyLCB2ZXJ0ZXguc2l6ZSA9IGNpdGluZ04sCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIGVkZ2UuY3VydmVkPS4yLCB2ZXJ0ZXguY29sb3IgPSBtZW1iZXJzaGlwKGNsbG4uY2l0KSkKYGBgCgojIENvbnN0cnVjdGlvbiBvZiB0aGUgZGlzY2lwbGluZSBzaW1pbGFyaXR5IG5ldHdvcmsKYGBge3IgZGlzY2lwbGluZU5ldHdvcmt9CmRpc2NpcGxpbmUycmVmIDwtIGFnZ3JlZ2F0ZShjaXRlc19vdXRbLGMoNjo3MSldLCBieT1saXN0KGNpdGVzX291dCRESVNDSVBMSU5FKSwgRlVOID0gc3VtTnVtKQpyb3duYW1lcyhkaXNjaXBsaW5lMnJlZikgPC0gZGlzY2lwbGluZTJyZWYkR3JvdXAuMQpkaXNjaXBsaW5lMnJlZiRHcm91cC4xIDwtIE5VTEwKY29scyA8LSBjb2xuYW1lcyhkaXNjaXBsaW5lMnJlZikKZm9yKGkgaW4gY29scyl7CiAgYWJzb2x1dGUgPC0gZGlzY2lwbGluZTJyZWZbLGldCiAgdG90YWwgPC0gc3VtKGFic29sdXRlKQogIHJlbGF0aXZlIDwtIGFic29sdXRlL3RvdGFsCiAgZGlzY2lwbGluZTJyZWZbLHBhc3RlMCgiZnJlcV8iLGkpXSA8LSByZWxhdGl2ZQp9CgpkaXNjMnJlZiA8LSBhcy5tYXRyaXgoZGlzY2lwbGluZTJyZWZbLDY3OjEzMl0pCmNvbG5hbWVzKGRpc2MycmVmKSA8LSBjb2xzCnNjYWxlZF9kaXNjMnJlZiA8LSBkaXNjMnJlZiAvIGNvbFN1bXMoZGlzYzJyZWYpCnRkaXNjMnJlZiA8LSB0KGRpc2MycmVmKQoKcmVmU2ltIDwtIHJvd25hbWVzKHRkaXNjMnJlZikKY29zU2ltIDwtIGRhdGEuZnJhbWUoKQprPTAKaWxpc3QgPC0gYygpCmZvcihpIGluIHJlZlNpbSl7CiAgaWxpc3QgPC0gYyhpbGlzdCwgaSkKICBmb3IoaiBpbiByZWZTaW0pewogICAgaWYgKGogJSFpbiUgaWxpc3QpewogICAgICBrIDwtIGsgKyAxCiAgICAgIGNvc1NpbVtrLDFdIDwtIGkKICAgICAgY29zU2ltW2ssMl0gPC0gagogICAgICB2aSA8LSB0ZGlzYzJyZWZbaSxdCiAgICAgIHZqIDwtIHRkaXNjMnJlZltqLF0KICAgICAgY29zU2ltW2ssM10gPC0gKHN1bU51bSh2aSAqIHZqKSkgLyAobm9ybV92ZWModmkpICogIG5vcm1fdmVjKHZqKSkgCiAgICB9CiAgfQp9CmNvbG5hbWVzKGNvc1NpbSkgPC0gYygnaScsICdqJywgJ2Nvc1NpbScpCndyaXRlLmNzdihjb3NTaW1bb3JkZXIoLWNvc1NpbSRjb3NTaW0pLF0sICJzaW1OZXRzL1NpbWlsYXJEaXNjaXBsaW5lc0NpdGVkX3JlbC5jc3YiKQpzdW1tYXJ5KGNvc1NpbSRjb3NTaW0pCmNzLmNpdCA8LSBjb3NTaW1bY29zU2ltJGNvc1NpbSA+PSAwLjksXQpnLmNpdCA8LSBncmFwaF9mcm9tX2RhdGFfZnJhbWUoY3MuY2l0LCBkaXJlY3RlZD1GKQoKZGlzQ2l0ZWROcyA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KHRvdXRjaXRlbWF0W3Jvd25hbWVzKHRkaXNjMnJlZikgJWluJSBWKGcuY2l0KSRuYW1lLF0sMSwgRlVOID0gbm9ybV92ZWMpKQpjb2xuYW1lcyhkaXNDaXRlZE5zKSA8LSAiZGlzQ2l0ZWROcyIKZGlzQ2l0ZWROcyRyZWYgPC0gcm93bmFtZXMoZGlzQ2l0ZWROcykKb3JkZXJlZE5hbWUgPC0gZGF0YS5mcmFtZShWKGcuY2l0KSRuYW1lKQpkaXNDaXRlZE5zIDwtIGRhdGEuZnJhbWUob3JkZXJlZE5hbWUsIGRpc0NpdGVkTnNbbWF0Y2gob3JkZXJlZE5hbWUkVi5nLmNpdC4ubmFtZSwgZGlzQ2l0ZWROcyRyZWYpLF0pWywiZGlzQ2l0ZWROcyJdCmRpc0NpdGVkTnMgPC0gZGlzQ2l0ZWROc1shaXMubmEoZGlzQ2l0ZWROcyldIAoKY29sbmFtZXMob3JkZXJlZE5hbWUpIDwtICJSRUZJRCIKcmVmaW5mbyA8LSBjaXRlc1sxOjY2LGMoIlJFRklEIiwgIkRJU0NJUExJTkUiKV0Kb3duX2Rpc2NpcGxpbmUgPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgcmVmaW5mb1ttYXRjaChvcmRlcmVkTmFtZSRSRUZJRCwgcmVmaW5mbyRSRUZJRCksXSkKb2Rpc2MgPC0gb3duX2Rpc2NpcGxpbmUkRElTQ0lQTElORQoKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5jaXQsMikKZy5jaXQkbGF5b3V0IDwtIGxheW91dApwYXIobWFyID0gYygwLDAsMCwwKSkKcGxvdChnLmNpdCwgZWRnZS53aWR0aCA9IHNxcnQoY3MuY2l0JGNvc1NpbSkgKiAyLCB2ZXJ0ZXguc2l6ZSA9IGRpc0NpdGVkTnMsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIGVkZ2UuY3VydmVkPS4yLCB2ZXJ0ZXguY29sb3IgPSBvZGlzYykKCgpgYGAKCiMgQ29uc3RydWN0aW9uIG9mIGZ1bGwtdGV4dCBzaW1pbGFyaXR5IG5ldHdvcmsKYGBge3IgZnVsbFRleHRTaW19CmRvY3MgPC0gdG1fbWFwKGRvY3MsIHRvU3BhY2UsICItIikKZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9TcGFjZSwgIjoiKQpkb2NzIDwtIHRtX21hcChkb2NzLCB0b1NwYWNlLCAiJyIpCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHRvU3BhY2UsICJgIikKZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9TcGFjZSwgIuKAmCIpCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHRvU3BhY2UsICJfIikKZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9TcGFjZSwgIuKAkyIpCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHRvU3BhY2UsICIvIikKZG9jcyA8LSB0bV9tYXAoZG9jcywgcmVtb3ZlUHVuY3R1YXRpb24pCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHRvbG93ZXIpICAgCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHJlbW92ZU51bWJlcnMpICAgCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkgICAKZHRtIDwtIERvY3VtZW50VGVybU1hdHJpeChkb2NzKSAgIApkdG0ubSA9IGFzLm1hdHJpeChkdG0pCnRkbSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoZG9jcykgICAKdGRtLm0gPSBhcy5tYXRyaXgodGRtKQoKIHRkbS5kZiA9IGFzLmRhdGEuZnJhbWUodGRtLm0pCiB0ZG0uZGYuZiA8LSB0ZG0uZGYgLyBjb2xTdW1zKHRkbS5kZikKCm5fd29yZHMgPC0gYXMuZGF0YS5mcmFtZShjb2xTdW1zKHRkbS5kZiwgbmEucm09VCkpCiBjb2xuYW1lcyhuX3dvcmRzKSA8LSAibl93b3JkcyIKIG5fd29yZHMkUkVGSUQgPC0gc3Vic3RyKHJvd25hbWVzKG5fd29yZHMpLCAxLDgpCiBuX3dvcmRzX2NvcnB1cyA8LSBkYXRhLmZyYW1lKGNpdGVzX2Zvcl9yZWZfemlwZnMsIG5fd29yZHNbbWF0Y2goY2l0ZXNfZm9yX3JlZl96aXBmcyRSRUZJRCwgbl93b3JkcyRSRUZJRCksXSkKIG5fd29yZHNfY29ycHVzJHJlZiA8LSBwYXN0ZShuX3dvcmRzX2NvcnB1cyRBVVRIT1IsIG5fd29yZHNfY29ycHVzJFlFQVIsIHNlcD0iICIpCiBuX3dvcmRzX2NvcnB1cyA8LSBuX3dvcmRzX2NvcnB1c1tuX3dvcmRzX2NvcnB1cyRBVVRIT1IgIT0gIktyYWtvdmVyIFMuIixdCiBxIDwtIGdncGxvdChuX3dvcmRzX2NvcnB1cywgYWVzKHg9cmVmLCB5ID0gbl93b3JkcykpCiBxICsgZ2VvbV9sb2xsaXBvcChhZXMocmVvcmRlcihyZWYsIC1uX3dvcmRzKSksY29sb3IgPSAic2VhZ3JlZW40IiwgY2V4PTEpICsKICAgY29vcmRfZmxpcCgpICsKICAgbGFicyh4PSJSZWZlcmVuY2UiLCB5PSJOdW1iZXIgb2Ygd29yZHMgYnkgY29ycHVzIGFydGljbGUiKQogCiB0ZXJtbWF0IDwtIHQoYXMubWF0cml4KHRkbS5kZi5mKSkKIAogcmVmU2ltVGVybSA8LSByb3duYW1lcyh0ZXJtbWF0KQogY29zU2ltVGVybSA8LSBkYXRhLmZyYW1lKCkKIGs9MAogaWxpc3QgPC0gYygpCiBmb3IoaSBpbiByZWZTaW1UZXJtKXsKICAgaWxpc3QgPC0gYyhpbGlzdCwgaSkKICAgZm9yKGogaW4gcmVmU2ltVGVybSl7CiAgICAgaWYgKGogJSFpbiUgaWxpc3QpewogICAgICAgayA8LSBrICsgMQogICAgICAgY29zU2ltVGVybVtrLDFdIDwtIGkKICAgICAgIGNvc1NpbVRlcm1baywyXSA8LSBqCiAgICAgICB2aSA8LSB0ZXJtbWF0W2ksXQogICAgICAgdmogPC0gdGVybW1hdFtqLF0KICAgICAgIGNvc1NpbVRlcm1baywzXSA8LSAoc3VtTnVtKHZpICogdmopKSAvIChub3JtX3ZlYyh2aSkgKiAgbm9ybV92ZWModmopKSAKICAgICB9CiAgIH0KIH0KIGNvbG5hbWVzKGNvc1NpbVRlcm0pIDwtIGMoJ2knLCAnaicsICdjb3NTaW1UZXJtJykKIHdyaXRlLmNzdihjb3NTaW1UZXJtW29yZGVyKC1jb3NTaW1UZXJtJGNvc1NpbVRlcm0pLF0sICJzaW1OZXRzL1NpbWlsYXJXb3JkaW5nLmNzdiIpCiBzdW1tYXJ5KGNvc1NpbVRlcm0pCgogY3MgPC0gY29zU2ltVGVybVtjb3NTaW1UZXJtJGNvc1NpbVRlcm0gPiAwLjcsXQogZy50ZXJtIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShjcywgZGlyZWN0ZWQ9RikKIHRvdGFsVGVybSA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KHRlcm1tYXRbcm93bmFtZXModGVybW1hdCkgJWluJSBWKGcudGVybSkkbmFtZSxdLDEsIEZVTiA9IG5vcm1fdmVjKSkKIGNvbG5hbWVzKHRvdGFsVGVybSkgPC0gInRvdGFsVGVybXMiCiB0b3RhbFRlcm0kcmVmIDwtIHJvd25hbWVzKHRvdGFsVGVybSkKIG9yZGVyZWROYW1lIDwtIGRhdGEuZnJhbWUoVihnLnRlcm0pJG5hbWUpCiB0b3RhbFRlcm1zIDwtIGRhdGEuZnJhbWUob3JkZXJlZE5hbWUsIHRvdGFsVGVybVttYXRjaChvcmRlcmVkTmFtZSRWLmcudGVybS4ubmFtZSwgdG90YWxUZXJtJHJlZiksXSlbLCJ0b3RhbFRlcm1zIl0KIHRvdGFsVGVybXMgPC0gdG90YWxUZXJtc1shaXMubmEodG90YWxUZXJtcyldIAogY2xsbi50ZXJtIDwtIGNsdXN0ZXJfbG91dmFpbihnLnRlcm0pCiBsYXlvdXQgPC0gbGF5b3V0X25pY2VseShnLnRlcm0sMikKIGcudGVybSRsYXlvdXQgPC0gbGF5b3V0CiBwYXIobWFyID0gYygwLDAsMCwwKSkKIHBsb3QoZy50ZXJtLCBlZGdlLndpZHRoID0gc3FydChjcyRjb3NTaW1UZXJtKSAqIDIsIHZlcnRleC5zaXplID0gdG90YWxUZXJtcyAqNTAsCiAgICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICAKICAgICAgZWRnZS5jdXJ2ZWQ9LjIsIHZlcnRleC5jb2xvciA9IG1lbWJlcnNoaXAoY2xsbi50ZXJtKSkKIApgYGAKCiMgQ29uc3RydWN0aW9uIGNvdW50cnkgc2ltaWxhcml0eSBuZXR3b3JrCmBgYHtyIGNvdW50cnlTaW19CgogIHBhcGVyTGlzdCA8LSBjb2xuYW1lcyhjaXRlc19vdXRbLDY6NzFdKQogIGNvdW50cnlEYXRhIDwtIGRhdGFbZGF0YSRURVJSSVRPUllfVFlQRSA9PSAiQ291bnRyeSIgJiBkYXRhJFJFRklEICVpbiUgcGFwZXJMaXN0LF0KY291bnRyeTJSZWYgPC0gdGFibGUoY291bnRyeURhdGEkQ05UUl9JRCwgY291bnRyeURhdGEkUkVGSUQpWy0xLF0KY291bnRyeTJSZWYubWF0IDwtIGFzLm1hdHJpeChjb3VudHJ5MlJlZltyb3dTdW1zKGNvdW50cnkyUmVmKT4wLGNvbG5hbWVzKGNvdW50cnkyUmVmKSAlaW4lIHBhcGVyTGlzdF0pCmNvdW50cnkyUmVmLm1hdFtjb3VudHJ5MlJlZi5tYXQ+MF0gPC0gMQpjb3VudHJ5bWF0IDwtIHQoY291bnRyeTJSZWYubWF0KQoKcmVmU2ltIDwtIHJvd25hbWVzKGNvdW50cnltYXQpCmNvc1NpbUMgPC0gZGF0YS5mcmFtZSgpCms9MAppbGlzdCA8LSBjKCkKZm9yKGkgaW4gcmVmU2ltKXsKICBpbGlzdCA8LSBjKGlsaXN0LCBpKQogIGZvcihqIGluIHJlZlNpbSl7CiAgICBpZiAoaiAlIWluJSBpbGlzdCl7CiAgICAgIGsgPC0gayArIDEKICAgICAgY29zU2ltQ1trLDFdIDwtIGkKICAgICAgY29zU2ltQ1trLDJdIDwtIGoKICAgICAgdmkgPC0gY291bnRyeW1hdFtpLF0KICAgICAgdmogPC0gY291bnRyeW1hdFtqLF0KICAgICAgcyA8LSAoc3VtTnVtKHZpICogdmopKSAvIChub3JtX3ZlYyh2aSkgKiAgbm9ybV92ZWModmopKSAKICAgICAgY29zU2ltQ1trLDNdIDwtIGlmZWxzZSghaXMubmEocyksIHMsIDApCiAgICB9CiAgfQp9CmNvbG5hbWVzKGNvc1NpbUMpIDwtIGMoJ2knLCAnaicsICdjb3NTaW1DJykKd3JpdGUuY3N2KGNvc1NpbUNbb3JkZXIoLWNvc1NpbUMkY29zU2ltQyksXSwgInNpbU5ldHMvU2ltaWxhckNvdW50cmllcy5jc3YiKQpzdW1tYXJ5KGNvc1NpbUMpCmNzLmNudHIgPC0gY29zU2ltQ1tjb3NTaW1DJGNvc1NpbUMgPj0gMC4yLF0KZy5jbnRyIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShjcy5jbnRyLCBkaXJlY3RlZD1GKQpjb3VudHJ5TiA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KGNvdW50cnltYXRbcm93bmFtZXMoY291bnRyeW1hdCkgJWluJSBWKGcuY250cikkbmFtZSxdLDEsIEZVTiA9IG5vcm1fdmVjKSkKY29sbmFtZXMoY291bnRyeU4pIDwtICJuX2NvdW50cmllcyIKY291bnRyeU4kcmVmIDwtIHJvd25hbWVzKGNvdW50cnlOKQpvcmRlcmVkTmFtZSA8LSBkYXRhLmZyYW1lKFYoZy5jbnRyKSRuYW1lKQpvcmRlcmVkQ291bnRyeU4gPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgY291bnRyeU5bbWF0Y2gob3JkZXJlZE5hbWUkVi5nLmNudHIuLm5hbWUsIGNvdW50cnlOJHJlZiksXSlbLCJuX2NvdW50cmllcyJdCm9yZGVyZWRDb3VudHJ5TiA8LSBvcmRlcmVkQ291bnRyeU5bIWlzLm5hKG9yZGVyZWRDb3VudHJ5TildIApjbGxuLmNudHIgPC0gY2x1c3Rlcl9sb3V2YWluKGcuY250cikKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5jbnRyLDIpCmcuY250ciRsYXlvdXQgPC0gbGF5b3V0CiBwYXIobWFyID0gYygwLDAsMCwwKSkKIHBsb3QoZy5jbnRyLCBlZGdlLndpZHRoID0gc3FydChjcy5jbnRyJGNvc1NpbUMpICogMiwgdmVydGV4LnNpemUgPSBvcmRlcmVkQ291bnRyeU4gKiAyLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gbWVtYmVyc2hpcChjbGxuLmNudHIpKQoKYGBgCgojIENvbnN0cnVjdGlvbiBjaXR5IGRlZmluaXRpb24gc2ltaWxhcml0eSBuZXR3b3JrCmBgYHtyIGNpdHlEZWZTaW19CgpjaXR5RGF0YSA8LSBkYXRhWyFpcy5uYShkYXRhJFVSQkFOU0NBTEUpICYgZGF0YSRSRUZJRCAlaW4lIHBhcGVyTGlzdCxdCmNpdHkyUmVmIDwtIHRhYmxlKGNpdHlEYXRhJFVSQkFOU0NBTEUsIGNpdHlEYXRhJFJFRklEKVssXQpjaXR5MlJlZi5tYXQgPC0gYXMubWF0cml4KGNpdHkyUmVmW3Jvd1N1bXMoY2l0eTJSZWYpPjAsY29sbmFtZXMoY2l0eTJSZWYpICVpbiUgcGFwZXJMaXN0XSkKY2l0eTJSZWYubWF0W2NpdHkyUmVmLm1hdD4wXSA8LSAxCmNpdHltYXQgPC0gdChjaXR5MlJlZi5tYXQpCgpyZWZTaW0gPC0gcm93bmFtZXMoY2l0eW1hdCkKY29zU2ltQ3QgPC0gZGF0YS5mcmFtZSgpCms9MAppbGlzdCA8LSBjKCkKZm9yKGkgaW4gcmVmU2ltKXsKICBpbGlzdCA8LSBjKGlsaXN0LCBpKQogIGZvcihqIGluIHJlZlNpbSl7CiAgICBpZiAoaiAlIWluJSBpbGlzdCl7CiAgICAgIGsgPC0gayArIDEKICAgICAgY29zU2ltQ3RbaywxXSA8LSBpCiAgICAgIGNvc1NpbUN0W2ssMl0gPC0gagogICAgICB2aSA8LSBjaXR5bWF0W2ksXQogICAgICB2aiA8LSBjaXR5bWF0W2osXQogICAgICBzIDwtIChzdW1OdW0odmkgKiB2aikpIC8gKG5vcm1fdmVjKHZpKSAqICBub3JtX3ZlYyh2aikpIAogICAgICBjb3NTaW1DdFtrLDNdIDwtIGlmZWxzZSghaXMubmEocyksIHMsIDApCiAgICB9CiAgfQp9CmNvbG5hbWVzKGNvc1NpbUN0KSA8LSBjKCdpJywgJ2onLCAnY29zU2ltQ3QnKQp3cml0ZS5jc3YoY29zU2ltQ3Rbb3JkZXIoLWNvc1NpbUN0JGNvc1NpbUN0KSxdLCAic2ltTmV0cy9TaW1pbGFyQ2l0aWVzLmNzdiIpCnN1bW1hcnkoY29zU2ltQ3QpCmNzLmNpdHkgPC0gY29zU2ltQ3RbY29zU2ltQ3QkY29zU2ltQ3QgPj0gMC4xLF0KCmcuY2l0eSA8LSBncmFwaF9mcm9tX2RhdGFfZnJhbWUoY3MuY2l0eSwgZGlyZWN0ZWQ9RikKY2l0eU4gPC0gYXMuZGF0YS5mcmFtZShhcHBseShjaXR5bWF0W3Jvd25hbWVzKGNpdHltYXQpICVpbiUgVihnLmNpdHkpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKGNpdHlOKSA8LSAibl9jaXRpZXMiCmNpdHlOJHJlZiA8LSByb3duYW1lcyhjaXR5TikKb3JkZXJlZE5hbWUgPC0gZGF0YS5mcmFtZShWKGcuY2l0eSkkbmFtZSkKb3JkZXJlZGNpdHlOIDwtIGRhdGEuZnJhbWUob3JkZXJlZE5hbWUsIGNpdHlOW21hdGNoKG9yZGVyZWROYW1lJFYuZy5jaXR5Li5uYW1lLCBjaXR5TiRyZWYpLF0pWywibl9jaXRpZXMiXQpvcmRlcmVkY2l0eU4gPC0gb3JkZXJlZGNpdHlOWyFpcy5uYShvcmRlcmVkY2l0eU4pXSAKCmNsbG4uY2l0eSA8LSBjbHVzdGVyX2xvdXZhaW4oZy5jaXR5KQpsYXlvdXQgPC0gbGF5b3V0X25pY2VseShnLmNpdHksMikKZy5jaXR5JGxheW91dCA8LSBsYXlvdXQKIHBhcihtYXIgPSBjKDAsMCwwLDApKQogcGxvdChnLmNpdHksIGVkZ2Uud2lkdGggPSBzcXJ0KGNzLmNpdHkkY29zU2ltQ3QpICogMiwgdmVydGV4LnNpemUgPSBvcmRlcmVkY2l0eU4gKiAyLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gbWVtYmVyc2hpcChjbGxuLmNpdHkpKQoKYGBgCgoKIyBDb25zdHJ1Y3Rpb24gZGVjYWRlIHNpbWlsYXJpdHkgbmV0d29yawpgYGB7ciBkZWNhZGVTaW19CgpkZWNhZGVEYXRhIDwtIGRhdGFbIWlzLm5hKGRhdGEkREFURSkgJiBkYXRhJFJFRklEICVpbiUgcGFwZXJMaXN0LF0KZGVjYWRlRGF0YSRERUNBREUgPC0gcGFzdGUwKHN1YnN0cihhcy5jaGFyYWN0ZXIoZGVjYWRlRGF0YSREQVRFKSwgMSwgMyksIDAsICJzIikKZGVjYWRlMlJlZiA8LSB0YWJsZShkZWNhZGVEYXRhJERFQ0FERSwgZGVjYWRlRGF0YSRSRUZJRClbLF0KZGVjYWRlMlJlZi5tYXQgPC0gYXMubWF0cml4KGRlY2FkZTJSZWZbcm93U3VtcyhkZWNhZGUyUmVmKT4wLGNvbG5hbWVzKGRlY2FkZTJSZWYpICVpbiUgcGFwZXJMaXN0XSkKZGVjYWRlMlJlZi5tYXRbZGVjYWRlMlJlZi5tYXQ+MF0gPC0gMQpkZWNhZGVtYXQgPC0gdChkZWNhZGUyUmVmLm1hdCkKCnJlZlNpbSA8LSByb3duYW1lcyhkZWNhZGVtYXQpCmNvc1NpbUN0IDwtIGRhdGEuZnJhbWUoKQprPTAKaWxpc3QgPC0gYygpCmZvcihpIGluIHJlZlNpbSl7CiAgaWxpc3QgPC0gYyhpbGlzdCwgaSkKICBmb3IoaiBpbiByZWZTaW0pewogICAgaWYgKGogJSFpbiUgaWxpc3QpewogICAgICBrIDwtIGsgKyAxCiAgICAgIGNvc1NpbUN0W2ssMV0gPC0gaQogICAgICBjb3NTaW1DdFtrLDJdIDwtIGoKICAgICAgdmkgPC0gZGVjYWRlbWF0W2ksXQogICAgICB2aiA8LSBkZWNhZGVtYXRbaixdCiAgICAgIHMgPC0gKHN1bU51bSh2aSAqIHZqKSkgLyAobm9ybV92ZWModmkpICogIG5vcm1fdmVjKHZqKSkKICAgICAgY29zU2ltQ3RbaywzXSA8LSBpZmVsc2UoIWlzLm5hKHMpLCBzLCAwKQogICAgfQogIH0KfQpjb2xuYW1lcyhjb3NTaW1DdCkgPC0gYygnaScsICdqJywgJ2Nvc1NpbUN0JykKd3JpdGUuY3N2KGNvc1NpbUN0W29yZGVyKC1jb3NTaW1DdCRjb3NTaW1DdCksXSwgInNpbU5ldHMvU2ltaWxhckRlY2FkZXMuY3N2IikKc3VtbWFyeShjb3NTaW1DdCRjb3NTaW1DdCkKY3MuZGVjYWRlIDwtIGNvc1NpbUN0W2Nvc1NpbUN0JGNvc1NpbUN0ID49IDAuNjUsXQoKZy5kZWNhZGUgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLmRlY2FkZSwgZGlyZWN0ZWQ9RikKZGVjYWRlTiA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KGRlY2FkZW1hdFtyb3duYW1lcyhkZWNhZGVtYXQpICVpbiUgVihnLmRlY2FkZSkkbmFtZSxdLDEsIEZVTiA9IG5vcm1fdmVjKSkKY29sbmFtZXMoZGVjYWRlTikgPC0gIm5fZGVjYWRlcyIKZGVjYWRlTiRyZWYgPC0gcm93bmFtZXMoZGVjYWRlTikKb3JkZXJlZE5hbWUgPC0gZGF0YS5mcmFtZShWKGcuZGVjYWRlKSRuYW1lKQpvcmRlcmVkZGVjYWRlTiA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCBkZWNhZGVOW21hdGNoKG9yZGVyZWROYW1lJFYuZy5kZWNhZGUuLm5hbWUsIGRlY2FkZU4kcmVmKSxdKVssIm5fZGVjYWRlcyJdCm9yZGVyZWRkZWNhZGVOIDwtIG9yZGVyZWRkZWNhZGVOWyFpcy5uYShvcmRlcmVkZGVjYWRlTildCgpjbGxuLmRlY2FkZSA8LSBjbHVzdGVyX2xvdXZhaW4oZy5kZWNhZGUpCmxheW91dCA8LSBsYXlvdXRfbmljZWx5KGcuZGVjYWRlLDIpCmcuZGVjYWRlJGxheW91dCA8LSBsYXlvdXQKcGFyKG1hciA9IGMoMCwwLDAsMCkpCnBsb3QoZy5kZWNhZGUsIGVkZ2Uud2lkdGggPSBzcXJ0KGNzLmRlY2FkZSRjb3NTaW1DdCkgKiAyLCB2ZXJ0ZXguc2l6ZSA9IG9yZGVyZWRkZWNhZGVOICogMiwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC43LCAgZWRnZS5jdXJ2ZWQ9LjIsIHZlcnRleC5jb2xvciA9IG1lbWJlcnNoaXAoY2xsbi5kZWNhZGUpKQogCmBgYAoKIyBDb25zdHJ1Y3Rpb24gb2YgdGhlIG5ldHdvcmtzIG9mIGFscGhhIHNpbWlsYXJpdHkKYGBge3IgYWxwaGFTaW19CmFscGhhRGF0YSA8LSBkYXRhWyFpcy5uYShkYXRhJEFMUEhBTE9US0EpICYgZGF0YSRSRUZJRCAlaW4lIHBhcGVyTGlzdCxdCmFscGhhRGF0YSRuIDwtIDEKbWVhbkFscGhhUGVyUmVmIDwtIGFnZ3JlZ2F0ZShhbHBoYURhdGFbLCJBTFBIQUxPVEtBIl0sIGJ5PWxpc3QoYWxwaGFEYXRhJFJFRklEKSwgRlVOPW1lYW5OdW0pCnNkQWxwaGFQZXJSZWYgPC0gYWdncmVnYXRlKGFscGhhRGF0YVssIkFMUEhBTE9US0EiXSwgYnk9bGlzdChhbHBoYURhdGEkUkVGSUQpLCBGVU49c2ROdW0pCnNkQWxwaGFQZXJSZWZbaXMubmEoc2RBbHBoYVBlclJlZiR4KSwieCJdIDwtIDAKbkFscGhhUGVyUmVmIDwtIGFnZ3JlZ2F0ZShhbHBoYURhdGFbLCJuIl0sIGJ5PWxpc3QoYWxwaGFEYXRhJFJFRklEKSwgRlVOPXN1bU51bSkKCnNpbWlsYXJBbHBoYSA8LSBjYmluZChtZWFuQWxwaGFQZXJSZWYsIHNkQWxwaGFQZXJSZWYsIG5BbHBoYVBlclJlZikKcm93bmFtZXMoc2ltaWxhckFscGhhKSA8LSBzaW1pbGFyQWxwaGEkR3JvdXAuMQpzaW1pbGFyQWxwaGFbLGMoMSwzLCA1KV0gPC0gTlVMTApjb2xuYW1lcyhzaW1pbGFyQWxwaGEpIDwtIGMoIm1lYW5BbHBoYSIsICJzZEFscGhhIiwgIm5BbHBoYSIpCgphbHBoYW1hdCA8LSBhcy5tYXRyaXgoc2ltaWxhckFscGhhKQoKbWVhbkRhdGEgPC0gbWVhbihhbHBoYURhdGFbLCJBTFBIQUxPVEtBIl0pCnNkRGF0YSA8LSBzZChhbHBoYURhdGFbLCJBTFBIQUxPVEtBIl0pCm1lYW5OIDwtIG1lYW4oc2ltaWxhckFscGhhJG5BbHBoYSkKCnJlZlNpbSA8LSByb3duYW1lcyhhbHBoYW1hdCkKZGlmZl9tZWFuIDwtIGRhdGEuZnJhbWUoKQpkaWZmX3NkIDwtIGRhdGEuZnJhbWUoKQpkaWZmX24gPC0gZGF0YS5mcmFtZSgpCms9MAppbGlzdCA8LSBjKCkKZm9yKGkgaW4gcmVmU2ltKXsKICBpbGlzdCA8LSBjKGlsaXN0LCBpKQogIGZvcihqIGluIHJlZlNpbSl7CiAgICBpZiAoaiAlIWluJSBpbGlzdCl7CiAgICAgIGsgPC0gayArIDEKICAgICAgZGlmZl9tZWFuW2ssMV0gPC0gaQogICAgICBkaWZmX21lYW5baywyXSA8LSBqCiAgICAgIG1pIDwtIHNpbWlsYXJBbHBoYVtpLDFdCiAgICAgIG1qIDwtIHNpbWlsYXJBbHBoYVtqLDFdCiAgICAgIG0gPC0gYWJzKChtaSAtIG1qKSAvIG1lYW5EYXRhKQogICAgICBkaWZmX21lYW5baywzXSA8LSBtCiAgICAgIAogICAgICBkaWZmX3NkW2ssMV0gPC0gaQogICAgICBkaWZmX3NkW2ssMl0gPC0gagogICAgICBzZGkgPC1zaW1pbGFyQWxwaGFbaSwyXQogICAgICBzZGogPC0gc2ltaWxhckFscGhhW2osMl0KICAgICAgc2QgPC0gYWJzKChzZGkgLSBzZGopIC8gc2REYXRhKQogICAgICBkaWZmX3NkW2ssM10gPC0gc2QKICAgICAgCiAgICAgIGRpZmZfbltrLDFdIDwtIGkKICAgICAgZGlmZl9uW2ssMl0gPC0gagogICAgICBuaSA8LXNpbWlsYXJBbHBoYVtpLDNdCiAgICAgIG5qIDwtIHNpbWlsYXJBbHBoYVtqLDNdCiAgICAgIG4gPC0gYWJzKChuaSAtIG5qKSAvIG1lYW5OKQogICAgICBkaWZmX25baywzXSA8LSBuCiAgICB9CiAgfQp9Cgpjb2xuYW1lcyhkaWZmX21lYW4pIDwtIGMoJ2knLCAnaicsICdkaWZmX21lYW4nKQp3cml0ZS5jc3YoZGlmZl9tZWFuW29yZGVyKGRpZmZfbWVhbiRkaWZmX21lYW4pLF0sICJzaW1OZXRzL2RpZmZfbWVhbi5jc3YiKQpzdW1tYXJ5KGRpZmZfbWVhbiRkaWZmX21lYW4pCmNvbG5hbWVzKGRpZmZfc2QpIDwtIGMoJ2knLCAnaicsICdkaWZmX3NkJykKd3JpdGUuY3N2KGRpZmZfc2Rbb3JkZXIoZGlmZl9zZCRkaWZmX3NkKSxdLCAic2ltTmV0cy9kaWZmX3NkLmNzdiIpCnN1bW1hcnkoZGlmZl9zZCRkaWZmX3NkKQpjb2xuYW1lcyhkaWZmX24pIDwtIGMoJ2knLCAnaicsICdkaWZmX24nKQp3cml0ZS5jc3YoZGlmZl9uW29yZGVyKGRpZmZfbiRkaWZmX24pLF0sICJzaW1OZXRzL2RpZmZfbi5jc3YiKQpzdW1tYXJ5KGRpZmZfbiRkaWZmX24pCgpgYGAKCiMjIFNpbWlsYXJpdHkgb2YgbWVhbiBhbHBoYQpgYGB7ciBtZWFuQWxwaGFTaW19CmNzLmFscGhhIDwtIGRpZmZfbWVhbltkaWZmX21lYW4kZGlmZl9tZWFuIDwgMC4wMjUsXQpnLmFscGhhIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShjcy5hbHBoYSwgZGlyZWN0ZWQ9RikKYWxwaGFNIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkoYWxwaGFtYXRbcm93bmFtZXMoYWxwaGFtYXQpICVpbiUgVihnLmFscGhhKSRuYW1lLF0sMSwgRlVOID0gbm9ybV92ZWMpKQpjb2xuYW1lcyhhbHBoYU0pIDwtICJtZWFuX2FscGhhcyIKYWxwaGFNJHJlZiA8LSByb3duYW1lcyhhbHBoYU0pCm9yZGVyZWROYW1lIDwtIGRhdGEuZnJhbWUoVihnLmFscGhhKSRuYW1lKQpvcmRlcmVkYWxwaGFNIDwtIGRhdGEuZnJhbWUob3JkZXJlZE5hbWUsIGFscGhhTVttYXRjaChvcmRlcmVkTmFtZSRWLmcuYWxwaGEuLm5hbWUsIGFscGhhTSRyZWYpLF0pWywibWVhbl9hbHBoYXMiXQpvcmRlcmVkYWxwaGFNIDwtIG9yZGVyZWRhbHBoYU1bIWlzLm5hKG9yZGVyZWRhbHBoYU0pXQpzaW1pbGFyQWxwaGEkUkVGSUQgPC0gcm93bmFtZXMoc2ltaWxhckFscGhhKQpjbGxuLmFscGhhIDwtIGNsdXN0ZXJfbG91dmFpbihnLmFscGhhKQpsYXlvdXQgPC0gbGF5b3V0X25pY2VseShnLmFscGhhLDIpCmcuYWxwaGEkbGF5b3V0IDwtIGxheW91dAoKbWVtYiA8LSBhcy5saXN0KG1lbWJlcnNoaXAoY2xsbi5hbHBoYSkpCgp2ZXJ0ZXhEYXRhIDwtIGRhdGEuZnJhbWUob3JkZXJlZFJFRklEPSBuYW1lcyhtZW1iZXJzaGlwKGNsbG4uYWxwaGEpKSkKdmVydGV4RGF0YSA8LSBkYXRhLmZyYW1lKHZlcnRleERhdGEsIHNpbWlsYXJBbHBoYVttYXRjaCh2ZXJ0ZXhEYXRhJG9yZGVyZWRSRUZJRCwgc2ltaWxhckFscGhhJFJFRklEKSxdKQoKZm9yIChyIGluIHZlcnRleERhdGEkUkVGSUQpewogIHZlcnRleERhdGFbdmVydGV4RGF0YSRSRUZJRCA9PSByLCJtZW1iX21lYW4iXSA8LSBtZW1iW3JdCn0KCnBhcihtYXIgPSBjKDAsMCwwLDApKQpwbG90KGcuYWxwaGEsIGVkZ2Uud2lkdGggPSBzcXJ0KGNzLmFscGhhJGRpZmZfbWVhbikgKiAyLCB2ZXJ0ZXguc2l6ZSA9IHZlcnRleERhdGEkbWVhbkFscGhhXjIgKiA1LAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gbWVtYmVyc2hpcChjbGxuLmFscGhhKSkKCiMgbWVhbiBhdmVyYWdlIHZhbHVlIG9mIGFscGhhIHJlcG9ydGVkIGJ5IGdyb3VwCmFnZ3JlZ2F0ZSh2ZXJ0ZXhEYXRhWywibWVhbkFscGhhIl0sIGJ5PWxpc3QodmVydGV4RGF0YSRtZW1iX21lYW4pLCBGVU49bWVhbk51bSkKCmBgYAoKIyMgU2ltaWxhcml0eSBvZiBzZCBhbHBoYQpgYGB7ciBzZEFscGhhU2ltfQpjcy5hbHBoYSA8LSBkaWZmX3NkW2RpZmZfc2QkZGlmZl9zZCA8IDAuMSxdCmcuYWxwaGEgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLmFscGhhLCBkaXJlY3RlZD1GKQphbHBoYVNEIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkoYWxwaGFtYXRbcm93bmFtZXMoYWxwaGFtYXQpICVpbiUgVihnLmFscGhhKSRuYW1lLF0sMSwgRlVOID0gbm9ybV92ZWMpKQpjb2xuYW1lcyhhbHBoYVNEKSA8LSAibWVhbl9zZHMiCmFscGhhU0QkcmVmIDwtIHJvd25hbWVzKGFscGhhU0QpCm9yZGVyZWROYW1lIDwtIGRhdGEuZnJhbWUoVihnLmFscGhhKSRuYW1lKQpvcmRlcmVkYWxwaGFTRCA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCBhbHBoYVNEW21hdGNoKG9yZGVyZWROYW1lJFYuZy5hbHBoYS4ubmFtZSwgYWxwaGFTRCRyZWYpLF0pWywibWVhbl9zZHMiXQpvcmRlcmVkYWxwaGFTRCA8LSBvcmRlcmVkYWxwaGFTRFshaXMubmEob3JkZXJlZGFscGhhU0QpXQoKY2xsbi5hbHBoYSA8LSBjbHVzdGVyX2xvdXZhaW4oZy5hbHBoYSkKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5hbHBoYSwyKQpnLmFscGhhJGxheW91dCA8LSBsYXlvdXQKCm1lbWIgPC0gYXMubGlzdChtZW1iZXJzaGlwKGNsbG4uYWxwaGEpKQoKdmVydGV4RGF0YSA8LSBkYXRhLmZyYW1lKG9yZGVyZWRSRUZJRD0gbmFtZXMobWVtYmVyc2hpcChjbGxuLmFscGhhKSkpCnZlcnRleERhdGEgPC0gZGF0YS5mcmFtZSh2ZXJ0ZXhEYXRhLCBzaW1pbGFyQWxwaGFbbWF0Y2godmVydGV4RGF0YSRvcmRlcmVkUkVGSUQsIHNpbWlsYXJBbHBoYSRSRUZJRCksXSkKCmZvciAociBpbiB2ZXJ0ZXhEYXRhJFJFRklEKXsKICB2ZXJ0ZXhEYXRhW3ZlcnRleERhdGEkUkVGSUQgPT0gciwibWVtYl9zZCJdIDwtIG1lbWJbcl0KfQoKcGFyKG1hciA9IGMoMCwwLDAsMCkpCnBsb3QoZy5hbHBoYSwgZWRnZS53aWR0aCA9IHNxcnQoY3MuYWxwaGEkZGlmZl9zZCkgKiAyLCB2ZXJ0ZXguc2l6ZSA9IHZlcnRleERhdGEkc2RBbHBoYSAqIDUwLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gbWVtYmVyc2hpcChjbGxuLmFscGhhKSkKCiMgbWVhbiBhdmVyYWdlIHZhbHVlIG9mIGFscGhhIHJlcG9ydGVkIGJ5IGdyb3VwCmFnZ3JlZ2F0ZSh2ZXJ0ZXhEYXRhWywic2RBbHBoYSJdLCBieT1saXN0KHZlcnRleERhdGEkbWVtYl9zZCksIEZVTj1tZWFuTnVtKQoKYGBgCgoKIyMgU2ltaWxhcml0eSBvZiBuIGFscGhhCmBgYHtyIG5BbHBoYVNpbX0KY3MuYWxwaGEgPC0gZGlmZl9uW2RpZmZfbiRkaWZmX24gPCAwLjEsXQpnLmFscGhhIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShjcy5hbHBoYSwgZGlyZWN0ZWQ9RikKYWxwaGFOIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkoYWxwaGFtYXRbcm93bmFtZXMoYWxwaGFtYXQpICVpbiUgVihnLmFscGhhKSRuYW1lLF0sMSwgRlVOID0gbm9ybV92ZWMpKQpjb2xuYW1lcyhhbHBoYU4pIDwtICJtZWFuX25zIgphbHBoYU4kcmVmIDwtIHJvd25hbWVzKGFscGhhTikKb3JkZXJlZE5hbWUgPC0gZGF0YS5mcmFtZShWKGcuYWxwaGEpJG5hbWUpCm9yZGVyZWRhbHBoYU4gPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgYWxwaGFOW21hdGNoKG9yZGVyZWROYW1lJFYuZy5hbHBoYS4ubmFtZSwgYWxwaGFOJHJlZiksXSlbLCJtZWFuX25zIl0Kb3JkZXJlZGFscGhhTiA8LSBvcmRlcmVkYWxwaGFOWyFpcy5uYShvcmRlcmVkYWxwaGFOKV0KCmNsbG4uYWxwaGEgPC0gY2x1c3Rlcl9sb3V2YWluKGcuYWxwaGEpCmxheW91dCA8LSBsYXlvdXRfbmljZWx5KGcuYWxwaGEsMikKZy5hbHBoYSRsYXlvdXQgPC0gbGF5b3V0CgptZW1iIDwtIGFzLmxpc3QobWVtYmVyc2hpcChjbGxuLmFscGhhKSkKCnZlcnRleERhdGEgPC0gZGF0YS5mcmFtZShvcmRlcmVkUkVGSUQ9IG5hbWVzKG1lbWJlcnNoaXAoY2xsbi5hbHBoYSkpKQp2ZXJ0ZXhEYXRhIDwtIGRhdGEuZnJhbWUodmVydGV4RGF0YSwgc2ltaWxhckFscGhhW21hdGNoKHZlcnRleERhdGEkb3JkZXJlZFJFRklELCBzaW1pbGFyQWxwaGEkUkVGSUQpLF0pCgpmb3IgKHIgaW4gdmVydGV4RGF0YSRSRUZJRCl7CiAgdmVydGV4RGF0YVt2ZXJ0ZXhEYXRhJFJFRklEID09IHIsIm1lbWJfbiJdIDwtIG1lbWJbcl0KfQoKcGFyKG1hciA9IGMoMCwwLDAsMCkpCnBsb3QoZy5hbHBoYSwgZWRnZS53aWR0aCA9IHNxcnQoY3MuYWxwaGEkZGlmZl9uKSAqIDIsIHZlcnRleC5zaXplID0gdmVydGV4RGF0YSRuQWxwaGEgKiAwLjQsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIGVkZ2UuY3VydmVkPS4yLCB2ZXJ0ZXguY29sb3IgPSBtZW1iZXJzaGlwKGNsbG4uYWxwaGEpKQoKIyBtZWFuIGF2ZXJhZ2UgdmFsdWUgb2YgYWxwaGEgcmVwb3J0ZWQgYnkgZ3JvdXAKYWdncmVnYXRlKHZlcnRleERhdGFbLCJuQWxwaGEiXSwgYnk9bGlzdCh2ZXJ0ZXhEYXRhJG1lbWJfbiksIEZVTj1tZWFuTnVtKQoKCmBgYAoKIyBSZWdyZXNzaW9uIG1vZGVscyBvZiBzaW1pbGFyaXR5IGluIG1lYW4gYW5kIHNkIGFscGhhCiMjIFByZXBhcmF0aW9uIG9mIGRhdGEgCmBgYHtyIHByZXBtb2RlbGxpbmd9CgojIGltcG9ydCBkaWZmIGluIGFscGhhIG1lYW5zCm1lYW5BbHBoYUR5YWRzIDwtIHJlYWQuY3N2Migic2ltTmV0cy9kaWZmX21lYW4uY3N2Iiwgc2VwPSIsIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpWywtMV0KbWVhbkFscGhhRHlhZHMkZHlhZElEIDwtIHBhc3RlKG1lYW5BbHBoYUR5YWRzJGksIG1lYW5BbHBoYUR5YWRzJGosIHNlcCA9ICJfIikKbWVhbkFscGhhRHlhZHMkbWVhbkFscGhhU2ltIDwtIC1hcy5udW1lcmljKG1lYW5BbHBoYUR5YWRzJGRpZmZfbWVhbikKbWVhbkFscGhhRHlhZHNbLDE6M10gPC0gTlVMTApEWUFEUyA8LSBtZWFuQWxwaGFEeWFkcwpEWUFEX0lEX29yZGVyIDwtIERZQURTJGR5YWRJRAoKIyBpbXBvcnQgZGlmZiBpbiBhbHBoYSBzZApzZEFscGhhRHlhZHMgPC0gcmVhZC5jc3YyKCJzaW1OZXRzL2RpZmZfc2QuY3N2Iiwgc2VwPSIsIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpWywtMV0Kc2RBbHBoYUR5YWRzJGR5YWRJSiA8LSBwYXN0ZShzdWJzdHIoc2RBbHBoYUR5YWRzJGksIDEsIDgpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzdHIoc2RBbHBoYUR5YWRzJGosIDEsIDgpLCBzZXAgPSAiXyIpCnNkQWxwaGFEeWFkcyRkeWFkSkkgPC0gcGFzdGUoc3Vic3RyKHNkQWxwaGFEeWFkcyRpLCAxLCA4KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic3RyKHNkQWxwaGFEeWFkcyRqLCAxLCA4KSwgc2VwID0gIl8iKQpzZEFscGhhRHlhZHMkZHlhZElEIDwtIGlmZWxzZShzZEFscGhhRHlhZHMkZHlhZElKICVpbiUgRFlBRF9JRF9vcmRlciwgc2RBbHBoYUR5YWRzJGR5YWRJSiwgc2RBbHBoYUR5YWRzJGR5YWRKSSkKCnNkQWxwaGFEeWFkcyRzZEFscGhhU2ltIDwtIC1hcy5udW1lcmljKHNkQWxwaGFEeWFkcyRkaWZmX3NkKQpzZEFscGhhRHlhZHNbLDE6NV0gPC0gTlVMTApEWUFEUyA8LSBkYXRhLmZyYW1lKERZQURTLCBzZEFscGhhRHlhZHNbbWF0Y2goRFlBRFMkZHlhZElELCBzZEFscGhhRHlhZHMkZHlhZElEKSwic2RBbHBoYVNpbSJdKQoKIyBpbXBvcnQgZGlmZiBpbiBuIGFscGhhIApuQWxwaGFEeWFkcyA8LSByZWFkLmNzdjIoInNpbU5ldHMvZGlmZl9uLmNzdiIsIHNlcD0iLCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKVssLTFdCm5BbHBoYUR5YWRzJGR5YWRJSiA8LSBwYXN0ZShzdWJzdHIobkFscGhhRHlhZHMkaSwgMSwgOCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnN0cihuQWxwaGFEeWFkcyRqLCAxLCA4KSwgc2VwID0gIl8iKQpuQWxwaGFEeWFkcyRkeWFkSkkgPC0gcGFzdGUoc3Vic3RyKG5BbHBoYUR5YWRzJGksIDEsIDgpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzdHIobkFscGhhRHlhZHMkaiwgMSwgOCksIHNlcCA9ICJfIikKbkFscGhhRHlhZHMkZHlhZElEIDwtIGlmZWxzZShuQWxwaGFEeWFkcyRkeWFkSUogJWluJSBEWUFEX0lEX29yZGVyLCBuQWxwaGFEeWFkcyRkeWFkSUosIG5BbHBoYUR5YWRzJGR5YWRKSSkKCm5BbHBoYUR5YWRzJG5BbHBoYVNpbSA8LSAtYXMubnVtZXJpYyhuQWxwaGFEeWFkcyRkaWZmX24pCm5BbHBoYUR5YWRzWywxOjVdIDwtIE5VTEwKRFlBRFMgPC0gZGF0YS5mcmFtZShEWUFEUywgbkFscGhhRHlhZHNbbWF0Y2goRFlBRFMkZHlhZElELCBuQWxwaGFEeWFkcyRkeWFkSUQpLCJuQWxwaGFTaW0iXSkKCiMgaW1wb3J0IHNpbWlsYXJpdHkgaW4gd29yZGluZyBhcyBleHBsYW5hdGlvbgp3b3JkaW5nRHlhZHMgPC0gcmVhZC5jc3YyKCJzaW1OZXRzL1NpbWlsYXJXb3JkaW5nLmNzdiIsIHNlcD0iLCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKVssLTFdCmhlYWQod29yZGluZ0R5YWRzKQp3b3JkaW5nRHlhZHMkZHlhZElKIDwtIHBhc3RlKHN1YnN0cih3b3JkaW5nRHlhZHMkaSwgMSwgOCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnN0cih3b3JkaW5nRHlhZHMkaiwgMSwgOCksIHNlcCA9ICJfIikKd29yZGluZ0R5YWRzJGR5YWRKSSA8LSBwYXN0ZShzdWJzdHIod29yZGluZ0R5YWRzJGksIDEsIDgpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzdHIod29yZGluZ0R5YWRzJGosIDEsIDgpLCBzZXAgPSAiXyIpCndvcmRpbmdEeWFkcyRkeWFkSUQgPC0gaWZlbHNlKHdvcmRpbmdEeWFkcyRkeWFkSUogJWluJSBEWUFEX0lEX29yZGVyLCB3b3JkaW5nRHlhZHMkZHlhZElKLCB3b3JkaW5nRHlhZHMkZHlhZEpJKQoKd29yZGluZ0R5YWRzJHdvcmRpbmdDb3NTaW0gPC0gYXMubnVtZXJpYyh3b3JkaW5nRHlhZHMkY29zU2ltVGVybSkKd29yZGluZ0R5YWRzWywxOjVdIDwtIE5VTEwKRFlBRFMgPC0gZGF0YS5mcmFtZShEWUFEUywgd29yZGluZ0R5YWRzW21hdGNoKERZQURTJGR5YWRJRCwgd29yZGluZ0R5YWRzJGR5YWRJRCksIndvcmRpbmdDb3NTaW0iXSkKCiMgaW1wb3J0IHNpbWlsYXJpdHkgaW4gY2l0YXRpb24gYXMgZXhwbGFuYXRpb24KY2l0YXRpb25EeWFkcyA8LSByZWFkLmNzdjIoInNpbU5ldHMvU2ltaWxhckNpdGF0aW9ucy5jc3YiLCBzZXA9IiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gRilbLC0xXQpjaXRhdGlvbkR5YWRzJGR5YWRJSiA8LSBwYXN0ZShjaXRhdGlvbkR5YWRzJGksIGNpdGF0aW9uRHlhZHMkaiwgc2VwID0gIl8iKQpjaXRhdGlvbkR5YWRzJGR5YWRKSSA8LSBwYXN0ZShjaXRhdGlvbkR5YWRzJGosIGNpdGF0aW9uRHlhZHMkaSwgc2VwID0gIl8iKQpjaXRhdGlvbkR5YWRzJGR5YWRJRCA8LSBpZmVsc2UoY2l0YXRpb25EeWFkcyRkeWFkSUogJWluJSBEWUFEX0lEX29yZGVyLCBjaXRhdGlvbkR5YWRzJGR5YWRJSiwgY2l0YXRpb25EeWFkcyRkeWFkSkkpCmNpdGF0aW9uRHlhZHMkY2l0YXRpb25Db3NTaW0gPC0gYXMubnVtZXJpYyhjaXRhdGlvbkR5YWRzJGNvc1NpbSkKY2l0YXRpb25EeWFkc1ssMTo1XSA8LSBOVUxMCkRZQURTIDwtIGRhdGEuZnJhbWUoRFlBRFMsIGNpdGF0aW9uRHlhZHNbbWF0Y2goRFlBRFMkZHlhZElELCBjaXRhdGlvbkR5YWRzJGR5YWRJRCksImNpdGF0aW9uQ29zU2ltIl0pCgojIGltcG9ydCBzaW1pbGFyaXR5IGluIGRpc2NpcGxpbmUgYXMgZXhwbGFuYXRpb24KZGlzY2lwbGluZUR5YWRzIDwtIHJlYWQuY3N2Migic2ltTmV0cy9TaW1pbGFyRGlzY2lwbGluZXNDaXRlZF9yZWwuY3N2Iiwgc2VwPSIsIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpWywtMV0KZGlzY2lwbGluZUR5YWRzJGR5YWRJSiA8LSBwYXN0ZShkaXNjaXBsaW5lRHlhZHMkaSwgZGlzY2lwbGluZUR5YWRzJGosIHNlcCA9ICJfIikKZGlzY2lwbGluZUR5YWRzJGR5YWRKSSA8LSBwYXN0ZShkaXNjaXBsaW5lRHlhZHMkaiwgZGlzY2lwbGluZUR5YWRzJGksIHNlcCA9ICJfIikKZGlzY2lwbGluZUR5YWRzJGR5YWRJRCA8LSBpZmVsc2UoZGlzY2lwbGluZUR5YWRzJGR5YWRJSiAlaW4lIERZQURfSURfb3JkZXIsIGRpc2NpcGxpbmVEeWFkcyRkeWFkSUosIGRpc2NpcGxpbmVEeWFkcyRkeWFkSkkpCmRpc2NpcGxpbmVEeWFkcyRkaXNjaXBsaW5lQ29zU2ltIDwtIGFzLm51bWVyaWMoZGlzY2lwbGluZUR5YWRzJGNvc1NpbSkKZGlzY2lwbGluZUR5YWRzWywxOjVdIDwtIE5VTEwKRFlBRFMgPC0gZGF0YS5mcmFtZShEWUFEUywgZGlzY2lwbGluZUR5YWRzW21hdGNoKERZQURTJGR5YWRJRCwgZGlzY2lwbGluZUR5YWRzJGR5YWRJRCksImRpc2NpcGxpbmVDb3NTaW0iXSkKCiMgaW1wb3J0IHNpbWlsYXJpdHkgaW4gY291bnRyaWVzIHN0dWRpZWQgYXMgY29udHJvbApjb3VudHJ5RHlhZHMgPC0gcmVhZC5jc3YyKCJzaW1OZXRzL1NpbWlsYXJDb3VudHJpZXMuY3N2Iiwgc2VwPSIsIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpWywtMV0KY291bnRyeUR5YWRzJGR5YWRJSiA8LSBwYXN0ZShjb3VudHJ5RHlhZHMkaSwgY291bnRyeUR5YWRzJGosIHNlcCA9ICJfIikKY291bnRyeUR5YWRzJGR5YWRKSSA8LSBwYXN0ZShjb3VudHJ5RHlhZHMkaiwgY291bnRyeUR5YWRzJGksIHNlcCA9ICJfIikKY291bnRyeUR5YWRzJGR5YWRJRCA8LSBpZmVsc2UoY291bnRyeUR5YWRzJGR5YWRJSiAlaW4lIERZQURfSURfb3JkZXIsIGNvdW50cnlEeWFkcyRkeWFkSUosIGNvdW50cnlEeWFkcyRkeWFkSkkpCmNvdW50cnlEeWFkcyRjb3VudHJ5Q29zU2ltIDwtIGFzLm51bWVyaWMoY291bnRyeUR5YWRzJGNvc1NpbUMpCmNvdW50cnlEeWFkc1ssMTo1XSA8LSBOVUxMCkRZQURTIDwtIGRhdGEuZnJhbWUoRFlBRFMsIGNvdW50cnlEeWFkc1ttYXRjaChEWUFEUyRkeWFkSUQsIGNvdW50cnlEeWFkcyRkeWFkSUQpLCJjb3VudHJ5Q29zU2ltIl0pCgojIGltcG9ydCBzaW1pbGFyaXR5IGluIGRlY2FkZXMgc3R1ZGllZCBhcyBjb250cm9sCmRlY2FkZUR5YWRzIDwtIHJlYWQuY3N2Migic2ltTmV0cy9TaW1pbGFyRGVjYWRlcy5jc3YiLCBzZXA9IiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gRilbLC0xXQpkZWNhZGVEeWFkcyRkeWFkSUogPC0gcGFzdGUoZGVjYWRlRHlhZHMkaSwgZGVjYWRlRHlhZHMkaiwgc2VwID0gIl8iKQpkZWNhZGVEeWFkcyRkeWFkSkkgPC0gcGFzdGUoZGVjYWRlRHlhZHMkaiwgZGVjYWRlRHlhZHMkaSwgc2VwID0gIl8iKQpkZWNhZGVEeWFkcyRkeWFkSUQgPC0gaWZlbHNlKGRlY2FkZUR5YWRzJGR5YWRJSiAlaW4lIERZQURfSURfb3JkZXIsIGRlY2FkZUR5YWRzJGR5YWRJSiwgZGVjYWRlRHlhZHMkZHlhZEpJKQpkZWNhZGVEeWFkcyRkZWNhZGVDb3NTaW0gPC0gYXMubnVtZXJpYyhkZWNhZGVEeWFkcyRjb3NTaW1DdCkKZGVjYWRlRHlhZHNbLDE6NV0gPC0gTlVMTApEWUFEUyA8LSBkYXRhLmZyYW1lKERZQURTLCBkZWNhZGVEeWFkc1ttYXRjaChEWUFEUyRkeWFkSUQsIGRlY2FkZUR5YWRzJGR5YWRJRCksImRlY2FkZUNvc1NpbSJdKQoKIyBpbXBvcnQgc2ltaWxhcml0eSBpbiBjaXR5IGRlZmluaXRpb24gdXNlZCBhcyBjb250cm9sCmNpdHlEZWZEeWFkcyA8LSByZWFkLmNzdjIoInNpbU5ldHMvU2ltaWxhckNpdGllcy5jc3YiLCBzZXA9IiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gRilbLC0xXQpjaXR5RGVmRHlhZHMkZHlhZElKIDwtIHBhc3RlKGNpdHlEZWZEeWFkcyRpLCBjaXR5RGVmRHlhZHMkaiwgc2VwID0gIl8iKQpjaXR5RGVmRHlhZHMkZHlhZEpJIDwtIHBhc3RlKGNpdHlEZWZEeWFkcyRqLCBjaXR5RGVmRHlhZHMkaSwgc2VwID0gIl8iKQpjaXR5RGVmRHlhZHMkZHlhZElEIDwtIGlmZWxzZShjaXR5RGVmRHlhZHMkZHlhZElKICVpbiUgRFlBRF9JRF9vcmRlciwgY2l0eURlZkR5YWRzJGR5YWRJSiwgY2l0eURlZkR5YWRzJGR5YWRKSSkKY2l0eURlZkR5YWRzJGNpdHlEZWZDb3NTaW0gPC0gYXMubnVtZXJpYyhjaXR5RGVmRHlhZHMkY29zU2ltQ3QpCmNpdHlEZWZEeWFkc1ssMTo1XSA8LSBOVUxMCkRZQURTIDwtIGRhdGEuZnJhbWUoRFlBRFMsIGNpdHlEZWZEeWFkc1ttYXRjaChEWUFEUyRkeWFkSUQsIGNpdHlEZWZEeWFkcyRkeWFkSUQpLCJjaXR5RGVmQ29zU2ltIl0pCgpjb2xuYW1lcyhEWUFEUykgPC0gYygiZHlhZElEIiwibWVhbkFscGhhU2ltIiwgInNkQWxwaGFTaW0iLCAibkFscGhhU2ltIiwgCiAgICAgICAgICAgICAgICAgICAgICJmdWxsVGV4dENvc1NpbSIsICJleHRlcm5hbENpdGF0aW9uQ29zU2ltIiwgImRpc2NpcGxpbmVDaXRhdGlvbkNvc1NpbSIsCiAgICAgICAgICAgICAgICAgICAgICJjb3VudHJpZXNDb3NTaW0iLCAiZGVjYWRlc0Nvc1NpbSIsICJjaXR5RGVmQ29zU2ltIikKCiMgc2NhbGUgYWxsIHZhcmlhYmxlcwpEWUFEUyRtZWFuQWxwaGFTaW1fc2NhbGVkIDwtIHNjYWxlKERZQURTJG1lYW5BbHBoYVNpbSkKRFlBRFMkc2RBbHBoYVNpbV9zY2FsZWQgPC0gc2NhbGUoRFlBRFMkc2RBbHBoYVNpbSkKRFlBRFMkbkFscGhhU2ltX3NjYWxlZCA8LSBzY2FsZShEWUFEUyRuQWxwaGFTaW0pCkRZQURTJGZ1bGxUZXh0Q29zU2ltX3NjYWxlZCA8LSBzY2FsZShEWUFEUyRmdWxsVGV4dENvc1NpbSkKRFlBRFMkZXh0ZXJuYWxDaXRhdGlvbkNvc1NpbV9zY2FsZWQgPC0gc2NhbGUoRFlBRFMkZXh0ZXJuYWxDaXRhdGlvbkNvc1NpbSkKRFlBRFMkZGlzY2lwbGluZUNpdGF0aW9uQ29zU2ltX3NjYWxlZCA8LSBzY2FsZShEWUFEUyRkaXNjaXBsaW5lQ2l0YXRpb25Db3NTaW0pCkRZQURTJGNvdW50cmllc0Nvc1NpbV9zY2FsZWQgPC0gc2NhbGUoRFlBRFMkY291bnRyaWVzQ29zU2ltKQpEWUFEUyRkZWNhZGVzQ29zU2ltX3NjYWxlZCA8LSBzY2FsZShEWUFEUyRkZWNhZGVzQ29zU2ltKQpEWUFEUyRjaXR5RGVmQ29zU2ltX3NjYWxlZCA8LSBzY2FsZShEWUFEUyRjaXR5RGVmQ29zU2ltKQoKRFlBRFN3aXRoTkEgPC0gRFlBRFMKRFlBRFMgPC0gRFlBRFNbY29tcGxldGUuY2FzZXMoRFlBRFMpLF0KCm1vZGVsZGF0YTwtIERZQURTWyxjKCJkeWFkSUQiLCJtZWFuQWxwaGFTaW1fc2NhbGVkIiwgInNkQWxwaGFTaW1fc2NhbGVkIiwgIm5BbHBoYVNpbV9zY2FsZWQiLAogICAgICAgICAgICAgICAgICAgICAiZnVsbFRleHRDb3NTaW1fc2NhbGVkIiwgImV4dGVybmFsQ2l0YXRpb25Db3NTaW1fc2NhbGVkIiwgImRpc2NpcGxpbmVDaXRhdGlvbkNvc1NpbV9zY2FsZWQiLAogICAgICAgICAgICAgICAgICAgICAiY291bnRyaWVzQ29zU2ltX3NjYWxlZCIsICJkZWNhZGVzQ29zU2ltX3NjYWxlZCIsICJjaXR5RGVmQ29zU2ltX3NjYWxlZCIpXQpjb2xuYW1lcyhtb2RlbGRhdGEpIDwtIGMoIklEIiwgImFscGhhIiwgInNkX2FscGhhIiwgIm5fZXN0aW0iLCJ0ZXh0IiwgImNpdGF0aW9uIiwgImRpc2NpcGxpbmUiLCAiY291bnRyeSIsICJkZWNhZGUiLCAiY2l0eSIpCgpgYGAKCgojIyBNb2RlbHMgb2YgbWVhbiBhbHBoYQpgYGB7ciBtZWFuQWxwaGFNb2RlbHN9CgpmdG1fYSA8LSBsbShkYXRhID0gbW9kZWxkYXRhLAogICAgICAgICAgICBmb3JtdWxhID0gYWxwaGEgfiB0ZXh0LAogICAgICAgICAgICBuYS5hY3Rpb24gPSBuYS5vbWl0KQplY21fYSA8LSBsbShkYXRhID0gbW9kZWxkYXRhLAogICAgICAgICAgICBmb3JtdWxhID0gYWxwaGEgfiBjaXRhdGlvbiwKICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEub21pdCkKZGNtX2EgPC0gbG0oZGF0YSA9IG1vZGVsZGF0YSwKICAgICAgICAgICAgZm9ybXVsYSA9IGFscGhhIH4gZGlzY2lwbGluZSwKICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEub21pdCkKY3RybV9hIDwtIGxtKGRhdGEgPSBtb2RlbGRhdGEsCiAgICAgICAgICAgIGZvcm11bGEgPSBhbHBoYSB+IG5fZXN0aW0gKwogICAgICAgICAgICAgY291bnRyeSAqIGRlY2FkZSAqIGNpdHksCiAgICAgICAgICAgIG5hLmFjdGlvbiA9IG5hLm9taXQpCmZ1bGxtb2RlbF9hIDwtIGxtKGRhdGEgPSBtb2RlbGRhdGEsCiAgICAgICAgICAgIGZvcm11bGEgPSBhbHBoYSB+IAogICAgICAgICAgICAgIHRleHQgKyBjaXRhdGlvbiArIGRpc2NpcGxpbmUgKyBuX2VzdGltICsKICAgICAgICAgICAgICBjb3VudHJ5ICogZGVjYWRlICogY2l0eSwKICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEub21pdCkKCnNnbTwtIHN0YXJnYXplcihmdG1fYSwgZWNtX2EsIGRjbV9hLAogICAgICAgICAgY3RybV9hLAogICAgICAgICAgZnVsbG1vZGVsX2EsCiAgICAgICAgICB0eXBlPSJ0ZXh0Iiwgb3V0PSJtb2RlbF9jb21wX3Jlc3VsdHNfbWVhbkFscGhhLmh0bWwiLCBmb250LnNpemUgPSAic21hbGwiLCBjb2x1bW4uc2VwLndpZHRoID0gIjFwdCIpCgpgYGAKCiMjIE1vZGVscyBvZiBzZCBhbHBoYQpgYGB7ciBzZEFscGhhTW9kZWxzfQoKZnRtX3NkIDwtIGxtKGRhdGEgPSBtb2RlbGRhdGEsCiAgICAgICAgICAgIGZvcm11bGEgPSBzZF9hbHBoYSB+IHRleHQsCiAgICAgICAgICAgIG5hLmFjdGlvbiA9IG5hLm9taXQpCmVjbV9zZCA8LSBsbShkYXRhID0gbW9kZWxkYXRhLAogICAgICAgICAgICBmb3JtdWxhID0gc2RfYWxwaGEgfiBjaXRhdGlvbiwKICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEub21pdCkKZGNtX3NkIDwtIGxtKGRhdGEgPSBtb2RlbGRhdGEsCiAgICAgICAgICAgIGZvcm11bGEgPSBzZF9hbHBoYSB+IGRpc2NpcGxpbmUsCiAgICAgICAgICAgIG5hLmFjdGlvbiA9IG5hLm9taXQpCiBuX3NkIDwtIGxtKGRhdGEgPSBtb2RlbGRhdGEsCiAgICAgICAgICAgICBmb3JtdWxhID0gc2RfYWxwaGEgfiBuX2VzdGltLAogICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEub21pdCkKY3RybV9zZCA8LSBsbShkYXRhID0gbW9kZWxkYXRhLAogICAgICAgICAgICAgZm9ybXVsYSA9IHNkX2FscGhhIH4gCiAgICAgICAgICAgICAgIGNvdW50cnkgKiBkZWNhZGUgKiBjaXR5LAogICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEub21pdCkKZnVsbG1vZGVsX3NkIDwtIGxtKGRhdGEgPSBtb2RlbGRhdGEsCiAgICAgICAgICAgICAgICAgIGZvcm11bGEgPSBzZF9hbHBoYSB+IAogICAgICAgICAgICAgICAgICAgIHRleHQgKyBjaXRhdGlvbiArIGRpc2NpcGxpbmUgKyBuX2VzdGltICsKICAgICAgICAgICAgICAgICAgICBjb3VudHJ5ICogZGVjYWRlICogY2l0eSwKICAgICAgICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEub21pdCkKCnNnbTwtIHN0YXJnYXplcihmdG1fc2QsIGVjbV9zZCwgZGNtX3NkLG5fc2QsCiAgICAgICAgICAgICAgICBjdHJtX3NkLAogICAgICAgICAgICAgICAgZnVsbG1vZGVsX3NkLAogICAgICAgICAgICAgICAgdHlwZT0idGV4dCIsIG91dD0ibW9kZWxfY29tcF9yZXN1bHRzX3NkQWxwaGEuaHRtbCIsIGZvbnQuc2l6ZSA9ICJzbWFsbCIsIGNvbHVtbi5zZXAud2lkdGggPSAiMXB0IikKCmBgYAoKIyMgUmVzaWR1YWxzIGFuYWx5c2lzCmBgYHtyIHJlc2lkdWFscywgd2FybmluZz1GQUxTRX0KCm1vZGVsZGF0YSRyZXMgPC0gZnVsbG1vZGVsX2EkcmVzaWR1YWxzCmhlYWQobW9kZWxkYXRhW29yZGVyKC1tb2RlbGRhdGEkcmVzKSxdKQptb2RlbGRhdGEkaSA8LSBzdWJzdHIobW9kZWxkYXRhJElELCAxLDgpCm1vZGVsZGF0YSRqIDwtIHN1YnN0cihtb2RlbGRhdGEkSUQsIDEwLCAxNykKCmNzLnJlc2lkdWFsc19yZXNQb3MgPC0gbW9kZWxkYXRhW21vZGVsZGF0YSRyZXMgPiAxLjEsYygiaSIsICJqIiwgInJlcyIpXQpnLnJlc2lkdWFscyA8LSBncmFwaF9mcm9tX2RhdGFfZnJhbWUoY3MucmVzaWR1YWxzX3Jlc1BvcywgZGlyZWN0ZWQ9RikKcmVzUG9zIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkoYWxwaGFtYXRbcm93bmFtZXMoYWxwaGFtYXQpICVpbiUgVihnLnJlc2lkdWFscykkbmFtZSxdLDEsIEZVTiA9IG5vcm1fdmVjKSkKY29sbmFtZXMocmVzUG9zKSA8LSAicmVzaWR1YWxzIgpyZXNQb3MkcmVmIDwtIHJvd25hbWVzKHJlc1BvcykKb3JkZXJlZE5hbWUgPC0gZGF0YS5mcmFtZShWKGcucmVzaWR1YWxzKSRuYW1lKQpvcmRlcmVkcmVzaWR1YWxzUmVzIDwtIGRhdGEuZnJhbWUob3JkZXJlZE5hbWUsIHJlc1Bvc1ttYXRjaChvcmRlcmVkTmFtZSRWLmcucmVzaWR1YWxzLi5uYW1lLCByZXNQb3MkcmVmKSxdKVssInJlc2lkdWFscyJdCm9yZGVyZWRyZXNpZHVhbHNSZXMgPC0gb3JkZXJlZHJlc2lkdWFsc1Jlc1shaXMubmEob3JkZXJlZHJlc2lkdWFsc1JlcyldCgpsYXlvdXQgPC0gbGF5b3V0X25pY2VseShnLnJlc2lkdWFscywyKQpnLnJlc2lkdWFscyRsYXlvdXQgPC0gbGF5b3V0CnBhcihtYXIgPSBjKDAsMCwxLDApKQpwbG90KGcucmVzaWR1YWxzLCBlZGdlLndpZHRoID0gc3FydChjcy5yZXNpZHVhbHNfcmVzUG9zJHJlcykgKiAyLCB2ZXJ0ZXguc2l6ZSA9IDIsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIGVkZ2UuY3VydmVkPS4yLCB2ZXJ0ZXguY29sb3IgPSAiZ3JlZW4iLCBlZGdlLmNvbG9yID0gImNvcmFsMyIsIAogICAgIG1haW4gPSAiTW9zdCBwb3NpdGl2ZSByZXNpZHVhbHMgaW4gbWVhbiBhbHBoYSBzaW1pbGFyaXR5IikKCgoKY3MucmVzaWR1YWxzX3Jlc05lZyA8LSBtb2RlbGRhdGFbbW9kZWxkYXRhJHJlcyA8IC0yLGMoImkiLCAiaiIsICJyZXMiKV0KZy5yZXNpZHVhbHMgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLnJlc2lkdWFsc19yZXNOZWcsIGRpcmVjdGVkPUYpCnJlc05lZyA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KGFscGhhbWF0W3Jvd25hbWVzKGFscGhhbWF0KSAlaW4lIFYoZy5yZXNpZHVhbHMpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKHJlc05lZykgPC0gInJlc2lkdWFscyIKcmVzTmVnJHJlZiA8LSByb3duYW1lcyhyZXNOZWcpCm9yZGVyZWROYW1lIDwtIGRhdGEuZnJhbWUoVihnLnJlc2lkdWFscykkbmFtZSkKb3JkZXJlZHJlc2lkdWFsc1JlcyA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCByZXNOZWdbbWF0Y2gob3JkZXJlZE5hbWUkVi5nLnJlc2lkdWFscy4ubmFtZSwgcmVzTmVnJHJlZiksXSlbLCJyZXNpZHVhbHMiXQpvcmRlcmVkcmVzaWR1YWxzUmVzIDwtIG9yZGVyZWRyZXNpZHVhbHNSZXNbIWlzLm5hKG9yZGVyZWRyZXNpZHVhbHNSZXMpXQoKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5yZXNpZHVhbHMsMikKZy5yZXNpZHVhbHMkbGF5b3V0IDwtIGxheW91dApwYXIobWFyID0gYygwLDAsMSwwKSkKcGxvdChnLnJlc2lkdWFscywgZWRnZS53aWR0aCA9IHNxcnQoY3MucmVzaWR1YWxzX3Jlc05lZyRyZXMpICogMiwgdmVydGV4LnNpemUgPSAyLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gIm9yYW5nZSIsIGVkZ2UuY29sb3IgPSAiZG9kZ2VyYmx1ZTMiLCAKICAgICBtYWluID0gIk1vc3QgbmVnYXRpdmUgcmVzaWR1YWxzIGluIG1lYW4gYWxwaGEgc2ltaWxhcml0eSIpCgoKCm1vZGVsZGF0YSRyZXMgPC0gZnVsbG1vZGVsX3NkJHJlc2lkdWFscwptb2RlbGRhdGEkaSA8LSBzdWJzdHIobW9kZWxkYXRhJElELCAxLDgpCm1vZGVsZGF0YSRqIDwtIHN1YnN0cihtb2RlbGRhdGEkSUQsIDEwLCAxNykKCmNzLnJlc2lkdWFsc19yZXNQb3MgPC0gbW9kZWxkYXRhW21vZGVsZGF0YSRyZXMgPiAxLGMoImkiLCAiaiIsICJyZXMiKV0KZy5yZXNpZHVhbHMgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLnJlc2lkdWFsc19yZXNQb3MsIGRpcmVjdGVkPUYpCnJlc1BvcyA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KGFscGhhbWF0W3Jvd25hbWVzKGFscGhhbWF0KSAlaW4lIFYoZy5yZXNpZHVhbHMpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKHJlc1BvcykgPC0gInJlc2lkdWFscyIKcmVzUG9zJHJlZiA8LSByb3duYW1lcyhyZXNQb3MpCm9yZGVyZWROYW1lIDwtIGRhdGEuZnJhbWUoVihnLnJlc2lkdWFscykkbmFtZSkKb3JkZXJlZHJlc2lkdWFsc1JlcyA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCByZXNQb3NbbWF0Y2gob3JkZXJlZE5hbWUkVi5nLnJlc2lkdWFscy4ubmFtZSwgcmVzUG9zJHJlZiksXSlbLCJyZXNpZHVhbHMiXQpvcmRlcmVkcmVzaWR1YWxzUmVzIDwtIG9yZGVyZWRyZXNpZHVhbHNSZXNbIWlzLm5hKG9yZGVyZWRyZXNpZHVhbHNSZXMpXQoKI2NsbG4ucmVzaWR1YWxzIDwtIGNsdXN0ZXJfbG91dmFpbihnLnJlc2lkdWFscykKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5yZXNpZHVhbHMsMikKZy5yZXNpZHVhbHMkbGF5b3V0IDwtIGxheW91dApwYXIobWFyID0gYygwLDAsMSwwKSkKcGxvdChnLnJlc2lkdWFscywgZWRnZS53aWR0aCA9IHNxcnQoY3MucmVzaWR1YWxzX3Jlc1BvcyRyZXMpICogMiwgdmVydGV4LnNpemUgPSAyLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gImdyZWVuIiwgZWRnZS5jb2xvciA9ICJjb3JhbDMiLCAKICAgICBtYWluID0gIk1vc3QgcG9zaXRpdmUgcmVzaWR1YWxzIGluIHNkIGFscGhhIHNpbWlsYXJpdHkiKQoKCgpjcy5yZXNpZHVhbHNfcmVzTmVnIDwtIG1vZGVsZGF0YVttb2RlbGRhdGEkcmVzIDwgLTEuNSxjKCJpIiwgImoiLCAicmVzIildCmcucmVzaWR1YWxzIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShjcy5yZXNpZHVhbHNfcmVzTmVnLCBkaXJlY3RlZD1GKQpyZXNOZWcgPC0gYXMuZGF0YS5mcmFtZShhcHBseShhbHBoYW1hdFtyb3duYW1lcyhhbHBoYW1hdCkgJWluJSBWKGcucmVzaWR1YWxzKSRuYW1lLF0sMSwgRlVOID0gbm9ybV92ZWMpKQpjb2xuYW1lcyhyZXNOZWcpIDwtICJyZXNpZHVhbHMiCnJlc05lZyRyZWYgPC0gcm93bmFtZXMocmVzTmVnKQpvcmRlcmVkTmFtZSA8LSBkYXRhLmZyYW1lKFYoZy5yZXNpZHVhbHMpJG5hbWUpCm9yZGVyZWRyZXNpZHVhbHNSZXMgPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgcmVzTmVnW21hdGNoKG9yZGVyZWROYW1lJFYuZy5yZXNpZHVhbHMuLm5hbWUsIHJlc05lZyRyZWYpLF0pWywicmVzaWR1YWxzIl0Kb3JkZXJlZHJlc2lkdWFsc1JlcyA8LSBvcmRlcmVkcmVzaWR1YWxzUmVzWyFpcy5uYShvcmRlcmVkcmVzaWR1YWxzUmVzKV0KCmxheW91dCA8LSBsYXlvdXRfbmljZWx5KGcucmVzaWR1YWxzLDIpCmcucmVzaWR1YWxzJGxheW91dCA8LSBsYXlvdXQKcGFyKG1hciA9IGMoMCwwLDEsMCkpCnBsb3QoZy5yZXNpZHVhbHMsIGVkZ2Uud2lkdGggPSBzcXJ0KGNzLnJlc2lkdWFsc19yZXNOZWckcmVzKSAqIDIsIHZlcnRleC5zaXplID0gMiwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC43LCAgZWRnZS5jdXJ2ZWQ9LjIsIHZlcnRleC5jb2xvciA9ICJvcmFuZ2UiLCBlZGdlLmNvbG9yID0gImRvZGdlcmJsdWUzIiwgCiAgICAgbWFpbiA9ICJNb3N0IG5lZ2F0aXZlIHJlc2lkdWFscyBpbiBzZCBhbHBoYSBzaW1pbGFyaXR5IikKCgpgYGAKCg==